【问题标题】:problem with constructors and g++ compile recipe构造函数和 g++ 编译配方的问题
【发布时间】:2020-01-17 00:00:20
【问题描述】:

我正在使用适用于 C++11 的函数创建一个 cpp 程序。即使代码看起来正确并且没有语法错误,我在编译时也会收到此消息:

/tmp/cce9dpew.o: In function `Object::Object()':
classes.cpp:(.text+0xd): undefined reference to `vtable for Object'
/tmp/cce9dpew.o: In function `Object::~Object()':
classes.cpp:(.text+0x45): undefined reference to `vtable for Object'
/tmp/cce9dpew.o:(.rodata._ZTI6String[_ZTI6String]+0x10): undefined reference to `typeinfo for Object'
collect2: error: ld returned 1 exit status

我必须在这里补充一点,如果我将所有这些 .cpp 和 .h 文件放在一个文件中,它会运行 Aok 打印构造函数和析构函数 cout 就可以了。 有人可以帮忙吗?代码如下。 编译我用来一起运行它们的配方: g++ -std=c++0x classes.h classes.cpp mainiz.cpp

classes.h:

#ifndef CLASSES_H
#define CLASSES_H

#include <iostream>
#include <cstring>
using namespace std;

class Object
{
    private:
        int id;
    public:
        Object();
        ~Object();
        void set_id(int ids);
        int get_id();
        void Equal(Object* bj) const;
        void Identical(Object* bj) const;
        virtual Object* clone();
        virtual void toString();        
};


class String:public Object
{
        string characters;
    public:
        String();
        ~String();
        void set_char(string a);
        string get_char();
        String* clone();
        void toString();    
        int Length();
        void Clear(string a);
        string& Concat(string &a);
        char At(char b);
        string& UpdateAt(string a,string charact);
        void Print(const string a) const;   
};

#endif //CLASSES_H

classes.cpp:

#include <iostream>
#include <cstring>

#include "classes.h"

using namespace std;

//FOR OBJECT CLASS
Object::Object(){ cout << "An object just got created." << endl;}

Object::~Object(){ cout << "An object just got destroyed." << endl; }

void Object::set_id(int ids) { this->id = ids; }
int Object::get_id() { return this->id;}

void Object::Equal(Object* bj) const
{
    if((this->id == bj->id))
    {
        cout << "The objects are equal." << endl;
    }
    else
    {
        cout << "The objects are not equal." <<endl;
    }
}

void Object::Identical(Object* bj) const
{
    if(this==bj)
    {
        cout << "The objects are identical." <<endl;
    }
    else
    {
        cout << "The objects are not identical." <<endl;
    }
}

//FOR STRING CLASS
String::String(){ cout << "String just created" << endl;}

String::~String(){ cout << "String to be destroyed" << endl;}

void String::set_char(string a) { this->characters = a;}
string String::get_char() { return this->characters;}

String* String::clone() { return this;}
void String::toString() {cout << "characters" << endl;}

int String::Length()
{ 
    string a = this->characters;
    return a.length();  
}

void String::Clear(string a)
{
    this->characters.clear();
}

string& String::Concat(string &a){  return (this->characters.append(a));}

char String::At(char b) { return (this->characters.find(b)); }

string& String::UpdateAt(string a,string charact)
{
    int position=this->characters.find(charact);
    return this->characters.replace(position,1,a);  
}

void String::Print(const string a) const { cout << "print of string:" << a << endl; }

mainiz.cpp:

#include <iostream>
#include <cstring>

#include "classes.h"

using namespace std;

int main()
{
    Object k;
    Object *st = new String;
    String d;
}

【问题讨论】:

  • 在旁注中,don't do using namespace std;Print() 不应使用 std::string 参数。
  • @ThomasSablik 感谢您分享此链接!好吧,我读了它,据我了解,我必须用我的虚拟机改变一些东西或使我的构造函数成为虚拟机?
  • @KenY-N 为什么我不应该使用它?我必须在我的函数中的所有内容前面写 std:: ..你为什么不建议它?
  • @ScatterBrainer Igor Tandetnik 为您的问题提供了解决方案。

标签: c++ class inheritance compiler-errors g++


【解决方案1】:

将 Object 类的析构函数设为“虚拟”,如果未定义对 Object::clone 和 Object::toString 的引用,则会出现另一个错误。

您可以尝试@Igor 的建议,但您当前的 mainiz.cpp 代码将无法工作,因为 C++ 不允许使用纯虚方法的类的实例。

你可以试试下面的代码:

class Object {
  virtual ~Object();

  virtual Object* clone();
  virtual void toString();
};

Object* Object::clone() {
  // Make your implementation here
  return nullptr;
}

void Object::toString() {
  // Make your implementation here
}

【讨论】:

  • 感谢您的回答! “因为 C++ 不允许使用纯虚拟方法的类的实例。” ....我无法理解这个...你能解释一下吗?
  • 当然,虚拟表存储虚拟方法以供以后用于每个实例。虚拟表允许 C++ 类继承,正如您可能已经知道的那样,仅允许子级覆盖父级的虚拟方法,我将其理解为将父级的方法替换为 vtable 中子级的方法。一个纯虚方法被声明为:“virtual void MyMethod() = 0;”,这意味着MyMethod没有body,并且vtable中的字段是空的,所以当链接器搜索那个方法的定义时它会遇到麻烦,因为它不知道使用哪个定义。
  • 并且该实例是不完整的,因为它声明了没有实际代码的方法。希望我解决了你的疑惑。 Here a reference
【解决方案2】:

Object::cloneObject::toString 已声明但从未实现。

如果您想让它们不实现,请将它们设为纯虚拟,如

class Object {
  virtual Object* clone() = 0;
};

【讨论】:

  • 问题是我不希望用户被允许克隆对象或使用 toString 对象...必须实现吗?
  • @ScatterBrainer clone 未实现。最后看到= 0;了吗?但是如果Object 是抽象类,则不能创建它的实例。
  • @ThomasSablik 是的,我不想实现它!对象是抽象的吗?
  • @ScatterBrainer 包含纯虚方法的类是抽象类,所以是的,Object 是抽象的
  • @ThomasSablik 我给出的代码不包含任何纯虚函数,所以我这样做的方式是对象抽象?
【解决方案3】:

上面给出的解决方案都不正确。问题出在我的编译配方中。这些函数在 C++11 之后开始存在,所以如果你使用类似的东西,你的编译配方应该是:

g++ -g -std=c++11 -o 可执行文件.cpp main.cpp

【讨论】:

  • 这应该不会影响任何事情。 (对我来说是Doesn't work。)您确定您没有对代码进行任何更改吗?
  • @HolyBlackCat 100% 肯定
  • g++ --version 说什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多