2013-09-11 83 views
1

我想创建一个具有纯虚函数的抽象类,该纯虚函数由非纯虚拟的构造函数调用。下面是我的文件class.hpp在非纯虚函数中使用纯虚函数的C++抽象类

#ifndef __CLASS_HPP__ 
#define __CLASS_HPP__ 

#include <iostream> 

class Parent { 
public: 
    Parent(){ 
    helloWorld(); // forced to say hello when constructor called      
    }; 
    virtual void helloWorld() = 0; // no standard hello...        
}; 

class Child : public Parent { 
public: 
    void helloWorld(){ // childs implementation of helloWorld       
    std::cout << "Hello, World!\n"; 
    }; 
}; 

#endif 

在这个例子中,我有了一个纯虚函数helloWorld()一个父类。我希望每个派生类在构造函数被调用时都会说“hello”;因此helloWorld()为什么在父类构造函数中。但是,我希望每个派生类都是FORCED,以选择它如何去说“你好”,而不是使用默认方法。这可能吗?如果我尝试用g ++编译这个,我得到了构造函数正在调用纯虚函数的错误。我main.cpp是:

#include "class.hpp" 

int main(){ 
    Child c; 
    return 0; 
} 

我使用g++ main.cpp -o main.out编译和所产生的误差是:

In file included from main.cpp:1:0: 
class.hpp: In constructor ‘Parent::Parent()’: 
class.hpp:9:16: warning: pure virtual ‘virtual void Parent::helloWorld()’ called from constructor [enabled by default] 

对于如何在合法的方式获得了类似的设置有什么建议?

新问题

DYP带来了我的注意,一个构造函数不使用任何重写功能,所以我希望能够做的是不可能在我把它设置的方式。但是,我仍然想强制任何派生的构造函数调用函数helloWorld(),有没有办法做到这一点?

+0

呼叫从一个构造函数虚函数(同一个对象的)的构造函数是危险的,因为它不” t调用派生类的重写。在这种情况下,它尝试调用纯粹的“Parent :: helloWorld”,因此*警告*(纯虚函数仍然可以实现)。您可以通过参数将派生类中的字符串传递给基类ctor,然后在基类中执行输出。也有可能:2阶段初始化。 – dyp

+0

基类依赖于这样的派生类似乎很奇怪。你能详细说明你想解决的问题吗?根据具体情况,可能有其他选项可用。 –

+0

在我的实际问题中,我有一个保存模拟数据的类。但是,在仿真中有很多功能取决于用户的偏好。我的基类是一个抽象类,它具有读入大量数据并存储它的构造函数,但留下了一些抽象函数(这些函数取决于uesr首选项)。所以我希望任何用户都被迫以相同的方式读取数据,但也被迫实现这些抽象函数。 – nick

回答

1

为什么不简单地将它添加到每个子类的构造函数中?

如果你想避免每次写它在构造函数(或者甚至逃课或继承它),那么你可以使用CRTP:

class Parent { 
public: 
    Parent(){}; 
    virtual void helloWorld() = 0; // no standard hello...        
}; 

template <typename Par> 
class ParentCRTP: public Parent { 
public: 
    ParentCRTP(){ 
    Par::doHelloWorld(); 
    }; 
    virtual void helloWorld(){ 
    Par::doHelloWorld(); 
    } 
}; 

class Child : public ParentCRTP<Child> { 
public: 
    static void doHelloWorld(){ // childs implementation of helloWorld       
    std::cout << "Hello, World!\n"; 
    }; 
}; 

这种做法不会给你一个指向子类你的孩子的hello方法 - 此时类实例只有Parent实例,没有有效的Child指针可以获得。为了在构造后强制执行Child的方法,您只能使用两个阶段初始化:首先使用构造函数创建类实例,然后使用单独的方法初始化它。

除此之外,像这样的问题可能是重新考虑你的设计的暗示。你不应该强迫你的类以特定的方式初始化自己。

2

你在做什么是非法的。

为了用C++定义一个抽象类,你的类必须至少有一个纯虚函数。在你的情况下

virtual void helloWorld() = 0; 

在这种情况下,你是对的。

但是你的纯虚函数没有任何实现,因为它是一个纯虚函数。因此,它是非法的同一类的constuructor调用纯虚函数。(在一流水平的纯虚函数没有任何实现)

所以,

Parent(){ 
helloWorld(); // forced to say hello when constructor called      
}; 

这是非法的。

如果你愿意,你可以实现你的纯虚函数在派生类中,然后调用helloWorld()从派生类

+0

这不会是我想要的。我希望每个子类都被迫调用'helloWorld()'。我写的代码将被其他人使用,我希望他们被迫调用该函数。 – nick

+0

我明白了。这就是为什么在父类构造函数中调用'helloWorld()'的原因。但是,情况是,如果你想定义一个抽象类,它必须包含至少一个纯虚函数。在你的情况下,它是'helloWorld()',它在父类级别没有实现。 – ANjaNA

+0

@nick你清楚吗? – ANjaNA