是否可以调用超类的构造函数,两个类远离C ++中的当前类

时间:2011-05-11 09:07:09

标签: c++ inheritance constructor

我有三个继承如下的类:

Class_A  
Class_B : public Class_A  
Class_C : public Class_B

Class_A包含一个构造函数:

public: Class_A(const char *name, int kind);

Class_B不包含该构造函数。

Class_C中,我希望调用Class_A的构造函数。类似的东西:
Class_C(const char *name, int kind) : Class_A::Class_A(name,kind) {}

问题在于我无法向Class_B添加中间构造函数,因为Class_B是生成的代码,每次我清理时都会重新生成。因此,我无法对Class_B进行任何持久的更改。不用说,Class_C中构造函数的上一行给出了error: "type 'Class_A' is not a direct base of ' Class_C '".

有没有办法可以调用子类Class_AClass_C的构造函数,而不需要Class_B中相同类型的构造函数?

7 个答案:

答案 0 :(得分:4)

如果你无法更改生成B的代码,那么你就不幸了,AFAIK。但是如果A类包含这样的构造函数,也许你可以添加一个简单的成员函数来设置这两个变量并从C构造函数中调用它?可能效率不高,但至少可行。

答案 1 :(得分:1)

如果可以使基类成​​为虚拟基类,则可以执行此操作,因为虚拟基础必须始终在最外层构造函数中未初始化。如果你无法改变ClassB从A继承的方式,你总是可以这样做:

RealClassA
ClassA : public virtual RealClassA
ClassB : public ClassA
ClassC : public ClassB

然后在ClassC构造函数中,您可以直接调用RealClassA(...)

通常虚拟遗产的特征是一个真正的痛苦,但它实际上可能对你有帮助。

答案 2 :(得分:1)

你可能已经塞满了(假设你不能改变B组的代),但是如果恰好有B的任何构造函数是模板,那么你可以专门化一个(对于一个唯一的虚拟类)并使用你想要的任何基类A构造创建自己的自定义构造函数....

否则,虽然效率较低,但显而易见,安全,干净的方法是使用A的operator=(如果有的话)来获取您想要的值......

C c;
c = A(x, y);

如果A的那些区域只能在施工时设置,那么这是一个更难的问题......

(暂时深入到未定义行为的可怕领域,你可以调用A的析构函数然后放置new它,但A的生命周期意味着跨越Bs和Cs。实际上,明显的风险是A创建类似于堆分配的值,B或C已经拥有指针,并且可能在析构函数释放后尝试使用....)

答案 3 :(得分:1)

唯一可能是Class_B实际上从中继承 Class_A;在这种情况下,将调用Class_A的构造函数 来自最派生的类。但由于这也涉及到改变 代码生成器,或代码生成器的输入,你可能会 好吧改变它以将附加构造函数添加到Class_B

如果你真的无法以某种方式更改代码生成器或其输入 会导致它生成额外的构造函数,但你可以 更改Class_AClass_C,然后有两种可能的解决方案:

  • 最简单的就是使用延迟初始化;添加一个功能 Class_A采用适当的参数,然后执行 构造函数完成后的初始化。虽然最简单, 只有在Class_A可以支持默认值时才能使用此方法 如果Class_A的所有成员都支持,那么也是如此 赋值,语义使得遵循默认构造 通过赋值与使用参数的构造具有相同的结果 你给(即没有参考成员,没有非成员,没有 const成员等)。
  • 或者,您可以放置​​所有功能(或至少 Class_A在一个单独的类中的数据成员,并且Class_A 虚拟地来自这个类。 Class_C然后会调用。{ 这个新类的构造函数。
  • 答案 4 :(得分:0)

    如果生成B,则更改生成器,否则您注定失败。

    根据B的作用,可能是一种解决方案,可以将您的设计更改为直接从A和B进行C派生(如果A是您的容器类,B是处理类)。执行此操作可能需要您使用模板B.如果B需要对A成员执行操作,您仍然可以给出指向B构造函数的A指针...

    答案 5 :(得分:0)

    您可以为Class_B添加一个构造函数,该构造函数与Class_A的ctor具有相同的签名,然后让Class_C在ctor中调用它。

    此外,类ctor初始化列表无法为基类中的成员设置值(无论它们是private protected还是public)。您必须使用基类'ctor来设置它们。

    答案 6 :(得分:0)

    按语言,不能访问非直接的基础构造函数。

    顺便说一下,如果Class_A构造函数签名是

    Class_A(const char *name, int kind);
    

    然后,Class_B应该有一些构造函数,它将接受给定类型的Class_A构造函数。否则会给编译器错误。

    摆脱该错误的唯一方法是为Class_A::Class_A(...)提供默认参数。