【问题标题】:virtual methods and constructors?虚拟方法和构造函数?
【发布时间】:2012-09-02 07:39:01
【问题描述】:

我有鸡肉鸡蛋问题。
我想为容器类创建接口,这样我就可以强制实现特定的属性访问器和其他方法,同时我希望能够从容器构造函数中调用这些方法。
但正如我们所知,从构造函数调用虚方法将调用基类方法,因为层次结构中的构造函数被调用的顺序。
所以问题是我需要虚拟方法来强制实现,但这是我不能在构造函数中调用的东西。
编辑:我希望在必须实现容器类(C1,C2 ...)时强制实现特定方法,其次我希望能够在容器构造函数中使用这些方法。简单来说,我想实现 INTERFACE 要求,仅声明混合。谢谢
你怎么解决这个问题 ?
以下是代码示例。

#include <iostream>
using namespace std;

class Base {
public: 
    virtual void myvirt() { cout << "Base::virt()" << endl; };
};

class C1 : public Base {
 public:
    C1() {cout << "C1()" << endl; C1::myvirt(); };
    C1(int i) { cout << "C1(int)" << endl; }
    void myvirt() { cout << "C1::virt" << endl;}
};


class C2 : public Base {
 public:
    C2() {cout << "C2()" << endl; C2::myvirt();};
    C2(int i) { cout << "C2(int)" << endl; }
    void myvirt() { cout << "C2::virt" << endl;}
};

template<class C = C1>
class Sc: public C {
 public:
    Sc() : C() { cout << "Sc()" << endl; };
    Sc(int n): C(n)  { cout << "Sc(int)" << endl; };

};


int main() {
    Sc<C2>  $sx(12);
    return 0;
}

正如我所问的,是否有某种方法可以强制在特定 Constructors() 的后代类中实现。 类似于“虚拟构造函数”。

【问题讨论】:

  • 不清楚你想要什么。
  • 您要调用哪些特定的派生方法?在构造对象之前调用对象的成员函数没有通用的解决方案。
  • 在 C1 的构造函数中调用虚函数会调用 C1 的重载,所以不清楚你需要做什么而你还没有做什么。
  • 主要是属性 getter/setters/checkers... 但我得出的结论相同,即没有通用的方法。大卫提出的克隆方法似乎是最好的方法。我只是不喜欢所涉及的多余语法。

标签: c++ constructor virtual


【解决方案1】:

首先,您不应该在构造或销毁期间调用虚函数。这根本不是一个好习惯。

Effective C++ 第三版第 9 条节选:

这种看似违反直觉的行为是有充分理由的。因为基类构造函数在派生类构造函数之前执行,所以在基类构造函数运行时派生类数据成员尚未初始化。如果在基类构造过程中调用的虚函数下降到派生类,派生类函数几乎肯定会引用本地数据成员,但这些数据成员还没有被初始化。那将是未定义行为和深夜调试会话的不间断票。调用对象中尚未初始化的部分本质上是危险的,因此 C++ 没有办法做到这一点。

http://www.artima.com/cppsource/nevercall.html

【讨论】:

  • 是的,我知道..这就是为什么在这里询问任何解决方法..即使用虚拟方法获得相同的效果
【解决方案2】:

只要让构造函数变得平凡,然后在构造函数返回后,调用某种初始化函数来完成对象的构造。您也可以使用clone 成语,这取决于您要如何决定要构造哪种对象。

你也可以有一个包装类,它的构造函数首先构造内部类,然后调用它的虚拟初始化函数。

更新:你可以这样换行:

 Class Wrapper : public Inner
 {
        public:
        Wrapper(...) : Inner(...)
        {
            init();
        }
        virtual ~Wrapper();
 }

现在你可以做

 Wrapper foo(whatever);

您可以像使用Inner 一样使用foo

【讨论】:

  • 嗯...谢谢,包装场景会是什么样子?似乎克隆/创建模式会起作用,我只是不想声明像“Sc var = x.create(5)”这样的变量,而只是说“Sc var(5);”
猜你喜欢
  • 2010-09-09
  • 2018-02-09
  • 2012-04-13
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
  • 2018-04-18
  • 2021-06-02
相关资源
最近更新 更多