覆盖默认构造函数/析构函数而不实现它们

时间:2013-10-18 14:51:07

标签: c++ constructor destructor

我有以下课程

    //myClass.h

    myClass{
    int data;
    public:
    myClass();
    void foo1(int);
    void foo2();
    ~myClass();
    };


    //myClass.cpp

    #include"myClass.h"
     myClass::foo1(int a){
    data = a ;
}

// main
int main(){
myClass m;
m.foo1(10);

}

为什么我们可以有一个非实现的函数(即头文件中的函数原型,但在.cpp文件中没有定义),但不是未实现的默认构造函数或析构函数?

如果我使默认构造函数/析构函数未实现(如上例所示),为什么会出现编译器错误?

当我没有实现构造函数时,我看到undefined reference to myClass::myClass(),而当我没有实现析构函数时,我看到undefined reference to vtable for myClass。但是,如果我实现这两个(即使使用空块{}),并且保留方法(例如foo2())未实现,编译器也不会抱怨。

构造函数/析构函数本质上只是类中的方法吗?如果是这样,为什么我有一个未定义的方法foo2(),但没有未定义的构造函数或析构函数?

如果有人可以帮助我理解这一点(而不只是“因为这就是它的方式”:),那将非常感激。

4 个答案:

答案 0 :(得分:4)

  

如果是这样,为什么我有一个未定义的方法foo2(),但没有未定义的构造函数或析构函数?

因为您正在使用构造函数和析构函数,而不是使用foo2()。添加一个调用,您将收到链接时错误。

答案 1 :(得分:3)

  

为什么我们可以拥有一个未实现的功能(即功能   标题中的原型,但在.cpp文件中没有定义),但不是   未实现的默认构造函数或析构函数?

你的断言是错误的。您可以拥有未实现的默认构造函数。实际上,这是确保您的类永远不会被隐式构造的一种方法。

  

如果我保持默认的构造函数/析构函数未实现(比如   上面的例子),为什么我会收到编译器错误?

因为您在代码中的某处使用它。重新读取编译器错误。它可能会告诉你确切的位置。

这就是:

int main(){
myClass m;
m.foo1(10);

myClass m;使用默认构造函数实例化myClass

如果不使用默认构造函数,则可以声明但不实现默认构造函数并编译清理。考虑:

class Foo 
{
public:
    Foo (int x) {}
    Foo();
};

int main()
{
    Foo f (1);
}

这里有Foo()的声明,但没有实现。代码编译时没有编译器或链接器错误。但是,此代码不会编译干净:

int main()
{
    Foo f;
}

后一个例子是你想要做的,在这里:

myClass m;

答案 2 :(得分:1)

编译器只关心你声明的代码(这是你的类声明所做的)。如果您声明构造函数,它会假定您已在某处实现了它。链接器将在您使用它时尝试查找该实现。对于构造函数/析构函数,在尝试创建类的实例时使用它。如果它们不存在,您将收到链接器错误。如果您不使用foo2(),并且未实现,则链接器不需要找到它,因此它不会尝试。因此,您不会收到链接器错误,您的代码将被成功编译并链接到可执行文件中。

答案 3 :(得分:0)

  

为什么我们可以有一个未实现的函数(即头文件中的函数原型,但.cpp文件中没有定义),但不是未实现的默认构造函数或析构函数?

必须定义任何使用的函数。如果不使用它们,大多数函数都可以保留未定义。

  

如果我保留默认构造函数/析构函数未实现(如上例所示),为什么会出现编译错误?

因为你的程序创建并销毁你的类的实例,它使用构造函数和析构函数;因为它们被使用,所以必须对它们进行定义。你已经宣布了它们,所以它们不会被隐含地定义;因此,你必须自己定义它们。

  

当我没有实现构造函数时,我看到了对myClass :: myClass()的未定义引用;

那是因为构造函数用于创建对象。

  

和myClass的vtable的未定义引用,当我没有实现析构函数时。

这是因为这个编译器在与析构函数相同的转换单元中生成vtable(如果它既不是隐式也不是内联的)。如果您没有声明析构函数但没有定义它,那么您也不会得到vtable

  

但是,如果我实现这两个(即使使用空块{}),并且保留一个未实现的方法(例如foo2()),编译器也不会抱怨。

那是因为你没有使用这个功能。如果你打电话给它,那你就会收到错误。

  

构造函数/析构函数本质上只是类中的方法吗?

或多或少,是的;但它们在各方面都很特别。语言规范将它们描述为“特殊成员函数”,并且整章描述了它们的属性。

  

如果是这样,为什么我有一个未定义的方法foo2(),但没有未定义的构造函数或析构函数?

重申:您必须定义您使用的任何内容。如果实例化类,则使用构造函数和析构函数。