在没有模板的情况下访问构造函数中的重写字段[关闭]

问题描述 投票:1回答:2

我不能从父C ++构造函数访问子类中的字段,我不能使用模板,因为上游项目不使用它们。

这是我尝试在C ++中重新实现的Python原型。该代码包含两个驱动程序类 - 一个子类和一个父类,父类在初始化期间打印该类的name

class Driver(object):
  name = "Unknown"
  def __init__(self):
    print(self.name)

class SpecificDriver(Driver):
  name = "Specific"
  def __init__(self):
    super(SpecificDriver, self).__init__()

Driver()
SpecificDriver()

这将两个字符串打印到控制台

Unknown
Specific

看起来在C ++中无法访问被覆盖的name,因为此时name不存在 - Call child method from parent constructor。那么也许有另一种方法可以在初始化时打印驱动程序name

更新(2018年):这个问题的原始标题是“在没有模板的C ++中初始化期间打印覆盖的子字段”,它被关闭得太宽。

python c++ inheritance override
2个回答
2
投票

尽管您要求在没有模板的情况下执行此操作,但这是从基类构造函数执行此操作的唯一方法。

以下是如何完成的示例:

struct IDriver {
    // Public virtual API:
    virtual void func1() = 0;
    // ...
    virtual ~IDriver() {}
};

template<typename Derived>
class Driver : public IDriver {
public:
    Driver() {
         std::cout << "Driver" << std::endl;
         std::cout << static_cast<Derived*>(this)->name() << std::endl;
    }   
};

class SpecificDriver : public Driver<SpecificDriver> {
public:
    // Public virtual API:
    virtual void func1();
    std::string name() const { return "SpecificDriver"; }
    // or use typeid(SpecificDriver).name() if you prefer
};

int main() {
    SpecificDriver sd;
}

Live Demo


至于你的评论:

是否可以像@tobspr方法一样使用额外的init()函数,但是将name命名为字段而不是函数调用?

好吧,既然类名是这些类的静态属性,你可以使用如下的static const字段:

template<typename Derived>
class Driver : public IDriver {
public:
    Driver() {
         std::cout << name << std::endl;
         std::cout << Derived::name << std::endl;
    }   

private:
    static const std::string name;
};

template<typename Derived>
const std::string Driver<Derived>::name = "Driver";

class SpecificDriver : public Driver<SpecificDriver> {
public:
    static const std::string name;
};

const std::string SpecificDriver::name = "SpecificDriver";

int main() {
    SpecificDriver sd;
}

Live Demo

甚至简化使用typeid()

#include <iostream>
#include <string>
#include <typeinfo>

template<typename Derived>
class Driver {
public:
    Driver() {
         std::cout << typeid(*this).name() << std::endl;
         std::cout << typeid(Derived).name() << std::endl;
    }  
};

class SpecificDriver : public Driver<SpecificDriver> {
};

int main() {
    SpecificDriver sd;
}

Live Demo


1
投票

假设您有两个类Base和Derived,Base构造函数对Derived类一无所知,这使得无法区分这两种类型。

由于您也不能(不应该)在构造函数中调用虚方法,因此常见的模式是创建init方法:

struct Base {
    virtual std::string get_name() { return "Base"; }
    void init() { std::cout << get_name(); }
};

struct Derived : public Base {
    virtual std::string get_name() { return "Derived"; }
};

// Later on ..
Base b;
b.init(); // Should print "Base"

Derived d;
d.init(); // Should print "Derived"

如您所见,这绝对不是最简单的解决方案。在这种情况下使用模板肯定会更好。

© www.soinside.com 2019 - 2024. All rights reserved.