簡體   English   中英

非純虛函數中使用純虛函數的c ++抽象類

[英]c++ abstract classes using pure virtual functions in non pure virtual functions

我想創建一個具有純虛函數的抽象類,該虛函數由並非純虛函數的構造函數調用。 以下是我的文件class.hpp

#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()在父類構造函數中。 但是,我希望每個派生類都必須被強制選擇“ hello”,而不要使用默認方法。 這可能嗎? 如果我嘗試使用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() ,有什么方法可以做到這一點?

您在做什么是非法的。

為了在C ++中定義一個抽象類,您的類必須至少具有一個純虛函數。 就你而言

virtual void helloWorld() = 0;

在這種情況下,您是對的。

但是您的純虛函數沒有任何實現,因為它是純虛函數。 因此從同一個類的構造函數中調用純虛函數是非法的。(在類級別上,純虛函數沒有任何實現)

所以,

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

這是非法的。

如果需要,可以在派生類中實現純虛函數,然后從派生類的構造函數中調用helloWorld()

您為什么不簡單地將其添加到每個子類的構造函數中?

如果要避免每次都在構造函數中編寫它(甚至跳過或繼承它),則可以使用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方法,只能使用兩個階段的初始化:首先,使用構造函數創建類實例,然后使用單獨的方法對其進行初始化。

除此之外,類似的問題可能是重新思考設計的提示。 您不應該強迫您的類以給定的方式初始化自身。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM