在没有模板的构造函数中访问覆盖的字段 [英] Access overridden field in constructor without templates

查看:92
本文介绍了在没有模板的构造函数中访问覆盖的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I can't access field overridden in child class from parent C++ constructor and I can not use templates, because upstream project doesn't use them.

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

This is working Python prototype that I try to reimplement in C++. The code contains two driver classes - one child and one parent, and parent prints name of the class during initialization.

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()

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

This prints two strings to console

Unknown
Specific

在C ++中看起来无法访问覆盖的name,因为此时name不存在-

Looks like in C++ can't access overridden name, because the name doesn't exist at this point - Call child method from parent constructor. So maybe there is another way to get driver name printed on initialization?

更新(2018):该问题的原标题是在C ++中初始化时在没有模板的情况下打印覆盖的子字段",并且由于范围太广而被关闭.

UPDATE (2018): The original title for this question was "Print overridden child field during initialization in C++ without templates" and it was closed as too broad.

推荐答案

尽管您要求不使用模板来执行此操作,但这是从基类构造函数执行此操作的唯一方法.

Despite you're asking to do this without templates, it's the only way to do this from a base class constructor.

以下是应如何操作的示例:

Here's a sample how it should be done:

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;
}

实时演示

至于您的评论:

是否可以像@tobspr方法中一样使用其他init()函数,但是将名称设为字段而不是函数调用?

Is it possible to use additional init() function as in @tobspr method, but making name a field instead of function call?

好吧,由于类名仍然是这些类的静态属性,因此您可以使用如下的static const字段:

Well, since the class name is a static property of these classes anyway, you can use a static const field like follows:

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;
}

实时演示

甚至简化使用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;
}

实时演示

这篇关于在没有模板的构造函数中访问覆盖的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆