关于c ++:如何在基类没有指定构造函数的情况下派生一个只有一个带有参数的构造函数的类的基类?

How to derive a base class with a class that only has a constructor with parameters when the base class doesn't specify a constructor?

我有一个从未实例化过的基类(我们称之为base class)(这是否称为虚拟基类?).另一个类(让我们调用usingclass)使用它,以便它可以将不同的派生类(derivedclassn)作为输入。因为我从未显式地实例化这个基类,所以我没有为它定义构造函数。派生类有一个构造函数,该构造函数采用基类不知道的类型,因此它不重写任何构造函数。我想知道为这两个类编写构造函数的正确方法。

现在,在baseclass i中,我声明在usingclass和derivedclass0中使用的公共变量和虚拟函数,重写这些函数,定义这些变量,并声明和定义接受参数的构造函数。但我得到以下错误:

1
2
3
4
undefined reference to `typeinfo for BaseClass'

undefined reference to `vtable for BaseClass'

test.o: In function `DerivedClass::~DerivedClass()'

我理解这是因为我从未为基类编写过构造函数或重写过无参数默认构造函数。但我这样做是没有意义的。派生类的构造函数的参数复杂到只在无参数的构造函数中实例化,而基类不知道派生类的参数以声明要覆盖的基类中的构造函数。所以我想知道我该怎么做。事先谢谢。

编辑

实际代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class BaseClass {
public:
    virtual ~BaseClass();
    virtual double  get(int the_params);
    virtual void    set(int he_params);
    int   _a_local;
};

class DerivedClass : public BaseClass {
    private:
        int _priveate_variables;
        void private_function();
    public:
        explicit DerivedClass(int the_int);
        virtual double  get(int the_int);
        virtual void    set(int the_int);
};

DerivedClass::DerivedClass(int the_int) : _priveate_variables(the_int) {
    _priveate_variables++;
    _a_local=_priveate_variables;
}


double DerivedClass::get(int the_int) {
     return 0.0;
}

void DerivedClass::set(int the_int) {
     _priveate_variables = 2;

}

错误

1
2
3
4
5
6
7
8
/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../lib/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'

/tmp/ccC1wbix.o: In function `BaseClass::BaseClass()':
CodeForThem.cc:(.text._ZN9BaseClassC2Ev[_ZN9BaseClassC5Ev]+0x9): undefined reference to `vtable for BaseClass'

/tmp/ccC1wbix.o: In function `DerivedClass::~DerivedClass()':
CodeForThem.cc:(.text._ZN12DerivedClassD2Ev[_ZN12DerivedClassD5Ev]+0x20): undefined reference to `BaseClass::~BaseClass()'

/tmp/ccC1wbix.o:(.rodata._ZTI12DerivedClass[_ZTI12DerivedClass]+0x10): undefined reference to `typeinfo for BaseClass'
collect2: error: ld returned 1 exit status

  • 你定义了virtual Base::~Base() {}吗?
  • 请显示实际代码,而不是代码的详细描述。
  • 是的,我有虚拟析构函数。很抱歉没有具体说明。我还添加了我们可以使用的实际代码。谢谢
  • 你的BaseClass虚析构函数、虚函数get和虚函数set至少应该定义一个实体(即使它是{}吗)?或者如果getset被假定为纯虚函数,那么应该在它们后面用= 0来定义它们?
  • @迈克尔:谢谢,就是这样。您的意思是分配运算符"="?
  • 不,我指的是函数声明上的= 0,它可以将它们定义为纯虚拟函数。像virtual double get(int the_params) = 0;一样。这将强制派生类提供函数get函数,否则将引发编译时错误。
  • 哦,酷,那比空的身体更干净。我也可以为析构函数这样做吗?
  • 不,不是在虚拟析构函数上。你需要提供一个身体(即使它什么都不做)


您不需要为BaseClass编写构造函数,它无论如何都会得到一个"默认构造函数"(和复制构造函数)。此编译器生成的默认构造函数将由DerivedClass构造函数自动调用。

至于链接错误,这可能是因为您没有为您的BaseClass定义虚拟析构函数。即使它是纯虚拟的(它应该是virtual,不管它是纯的(=0)还是非实质的),您也需要用一个空体来定义它。

  • "定义失败"有点强。代码有效;编译器错误。添加析构函数是众所周知的解决方法。
  • @彼得贝克:你是说现在使用的大多数编译器在拒绝试图实例化一个没有定义的纯虚拟析构函数的基类的代码时都有一个bug吗?这将是真正令人震惊的,并将违背公认的智慧在这个网站和许多其他。互联网上的共识似乎是C++实际上需要定义一个纯虚析构函数。你是说我们都搞错了吗?
  • 错误消息不是关于缺少析构函数定义的。他们说链接器找不到为DerivedClass的析构函数(可能是编译器生成的)生成的对象代码中提到的vtable和typeinfo信息。问题中没有任何内容可以指示基类被定义为具有纯虚拟析构函数。
  • @感谢大家的评论。它们都很有信息量。我看到了vitrual析构函数的问题,并检查了它,但我的问题是在其他地方。
  • @夏恩:好吧,所以你的问题实际上是你没有定义~BaseClass()。你只是在申报。你需要定义它,即使它是空的。
  • 我还应该为所有其他虚拟函数做同样的事情?编译器是否有充分的理由需要添加这些声明?
  • 请阅读"纯虚拟函数"。除了析构函数之外,您还可以使其他BaseClass函数纯粹是虚拟的,以避免定义它们。