【问题标题】:C++ inheritance and constructors, destructorsC++ 继承和构造函数、析构函数
【发布时间】:2012-11-14 17:16:36
【问题描述】:
//Parent.h
class Parent{
public:
   Parent(){}
   ~Parent(){}
   virtual void func1() = 0;
};

//Child.h
#include "Parent.h"
class Child : public Parent{
  int x, y;
public:
  Child() : Parent(){ //constructor

  }
  virtual void func1();
};

//Child.cpp
#include "Child.h"
void Child::Parent::func1(){

}

这编译得很好,但是,我想把 Child 类的构造函数(和析构函数)的实现放在它的 cpp 文件中,可以吗?怎么样?

我已经尝试了下面的代码,但它引发了对 vtable for Child 的未定义引用

Child::Child() : Parent(){  //in the cpp
}

Child(); //in the header file 
Child():Parent(); //also tried this one

【问题讨论】:

    标签: c++ inheritance constructor destructor


    【解决方案1】:

    你要做的几件事:

    • 保护发布您的头文件以防止意外的多次包含。
    • 使您的 Parent 析构函数虚拟化
    • 初始化非自动成员变量以确定值。

    您的最终布局可能如下所示。

    Parent.h

    #ifndef PARENT_H_
    #define PARENT_H_
    
    class Parent
    {
    public:
        Parent() {};
        virtual ~Parent() {};
    
    public:
        virtual void func1() = 0;
    };
    
    #endif // PARENT_H_
    

    Child.h

    #ifndef CHILD_H_
    #define CHILD_H_
    
    #include "Parent.h"
    
    class Child : public Parent
    {
        int x,y;
    
    public:
        Child();
        virtual ~Child();
    
        virtual void func1();
    };
    #endif
    

    Child.cpp

    Child::Child()
       : Parent()     // optional if default
       , x(0), y(0)   // always initialize members to determinate values
    {
    }
    
    Child::~Child()
    {
    }
    
    void Child::func1()
    {
    }
    

    【讨论】:

    • @markuz 我希望这是有道理的。养成现在初始化成员的习惯。引用是强制性的,一般来说,即使您的 POD 类型成员(普通旧数据)也是用 known 值初始化的,这是一种可靠的做法。
    【解决方案2】:
    $ cat Parent.h 
    #ifndef GUARD_PARENT_H_
    #define GUARD_PARENT_H_
    
    class Parent{
    public:
       Parent(){}
       ~Parent(){}
       virtual void func1() = 0;
    };
    
    #endif /* GUARD_PARENT_H_ */
    $ cat Child.h
    #ifndef GUARD_CHILD_H_
    #define GUARD_CHILD_H_
    
    #include "Parent.h"
    
    class Child : public Parent{
      int x, y;
    public:
      Child();
      virtual void func1();
    };
    
    #endif /* GUARD_CHILD_H_ */
    $ cat Child.cpp
    #include "Child.h"
    
    Child::Child() : Parent() {
    }
    
    void Child::func1(){
    }
    $ cat try.cc
    #include "Child.h"
    
    int main() {
            Child c;
    }
    $ g++ try.cc Child.cpp
    $ ./a.out
    $
    

    【讨论】:

    • +1 -- 但 Parent 的析构函数应该是 virtualprotected
    • 是的,没关系。但是在向初学者解释事情时,这是一个陷阱,你不应该只是“从问题中复制”。
    • 谢谢你们两个。顺便说一句,你怎么称呼你所做的?添加警卫的东西,所以我可以谷歌它并阅读更多关于它的信息。
    • 我认为“包括警卫”是通常的名称。 (它们在那里是因为我的编辑器会在我开始一个新的.h 文件时自动添加它们。)
    • 拒绝纠正虚拟析构函数问题,不能是正确答案。
    猜你喜欢
    • 2011-12-27
    • 2013-12-24
    • 2016-03-24
    • 2014-11-22
    • 2012-04-28
    • 2019-01-21
    • 1970-01-01
    • 2018-06-28
    相关资源
    最近更新 更多