三规则和继承

时间:2011-10-25 07:07:44

标签: c++ inheritance

class A定义了copy operator,析构函数和operator =。 (Rule of Three

如果B继承自A

  • 将自动调用析构函数
  • 我需要链接构造函数
  • operator= ...我应该为班级B明确定义吗?

5 个答案:

答案 0 :(得分:6)

不,这是不必要的。

如果你仔细阅读“三法则”,你会注意到没有关于基类的说法,只能根据类的适当属性和行为做出决定。

(Check this example on ideone)

#include <iostream>

struct A {
  A(): a(0) {}
  A& operator=(A const& rhs) { a = rhs.a; return *this; }
  int a;
};

struct B: A { B(): b(0) {} int b; };

int main() {
  B foo;
  foo.a = 1;
  foo.b = 2;

  B bar;
  bar = foo;

  std::cout << bar.a << " " << bar.b << "\n";
}

// Output: 1 2

这实际上是封装的真正力量。因为您成功使用 Rule of Three ,在使基类 sane 的行为时,其派生类无需知道复制构造函数是否由编译器默认或手动(和复杂)实现,所有对用户而言都很重要(而派生类是用户),是复制构造函数执行复制。

Rule of Three 提醒我们实现细节以帮助实现正确的语义。与所有实现细节一样,它仅对该类的实现者和维护者有用。

答案 1 :(得分:2)

同样的三个规则也适用于派生类 该规则适用于所有类,您可以将它应用于继承层次结构中的每个类,就像将其应用于单个类一样。

如果您的class B需要三巨头的两个中的任何一个(复制构造函数和析构函数),那么您需要将复制赋值运算符定义为好。

所以它实际上取决于Derived类的成员&amp;您希望Derived类对象的行为。

例如:
如果派生类成员由任何指针成员组成,并且您需要深层副本,那么根据Rule of 3,您的派生类需要重载并为三巨头提供自己的实现。

答案 2 :(得分:1)

  

将自动调用析构函数

为了一致性

,最好在派生类B中定义析构函数
  

我需要链接构造函数

当然。如果基本构造函数是默认的,那么它的一致性仍然更好。

  

operator = ...我应该为B类明确定义吗?

是的,就像这样:

struct A
{
  A& operator=( const A & r )
  {
    // assign all A's member variables
    return *this;
  }
};

struct B : public A
{
  B& operator=( const B & r )
  {
    A::operator=( r );
    // assign all B's member variables
    return *this;
  }
};

答案 3 :(得分:1)

Als说的是正确的,但我不确定他是否回答了你的问题。如果你想在B中做任何具体的事情,除了你在A三巨头中已经做过的事情之外,那么你也没有理由定义B的三巨头。

如果你确实需要其中一个,那么应该适用三个规则。

答案 4 :(得分:0)

这是一个示例代码和输出:

#include <iostream>

class A{
 int a;
 public:
 A():a(0){}
 A(A const & obj){std::cout << "CC called\n"; a = obj.a;}
 A & operator =(A & a){std::cout << "operator= called\n"; return a;}
 ~A(){std::cout << "A::dtor called\n";}
};

class B: public A{
};

int main(){ 
 B b,v;
 b=v;
}

输出:

operator= called
A::dtor called
A::dtor called