C++无法访问父媒体资源的子媒体资源

C++ can't access child property from parent

本文关键字:媒体 资源 访问 C++      更新时间:2023-10-16

谁能解释为什么Driver init()方法无法打印name子项中覆盖的属性?

#include <iostream>
#include <string>
class Driver {
public:
    std::string name = "Unknown";
    void init() {
        std::cout << name << std::endl;
    }
};
// need public here to inherit init()
class SpecificDriver : public Driver {
public:
    std::string name = "Specific";
};
int main() {
    Driver d;
    SpecificDriver sd;
    // this gives Unknown Unknown =/
    d.init();
    sd.init();
}

这给出了:

Unknown
Unknown

并且应该是:

Unknown
Specific

现场演示

你没有做你认为你可能做的事情。您正在驱动程序中声明变量"名称",在特定驱动程序中声明变量"名称"。调用基类驱动程序中定义的init()时,该驱动程序只能访问其自己的值为"unknown"的name字段。

相反,您应该使用构造函数初始化"name"变量。

喜欢这个:

class Driver {
public:
    std::string name;
    Driver():name("Unknown"){} //default
    Driver(std::string value):name(value){}
    void init() {
        std::cout << name << std::endl;
    }
};
// need public here to inherit init()
class SpecificDriver : public Driver {
public:
    SpecificDriver():Driver("Specific"){}
};
int main() {
    Driver d;
    SpecificDriver sd;
    d.init();
    sd.init();
}

编辑:现场演示 http://coliru.stacked-crooked.com/a/c453758867454348

在C++中,虚拟继承是选择加入而不是隐式的。

当你有这个代码时

class Driver {
public:
    std::string name = "Unknown";
    void init() {
        std::cout << name << std::endl;
    }
};

符号name将根据当时范围内的内容进行静态解析。

如果稍后声明全局变量name则它对此代码的含义没有影响。如果您稍后从此类 Driver 派生,则 init 函数在继承该类时不会具有不同的含义,如您的示例所示。

此"静态"调度是C++中的默认行为,因为它是最简单、最快的。特别是,如果您稍后使用模板和继承来执行操作,则以这种方式工作很重要,否则许多代码将产生大量额外的开销。

Alex Zywicki展示了一种实现自己想要的东西的方法。另一种方法是使用虚拟调度来获取字符串。像这样:

class Driver {
public:
    virtual std::string name() const {
        return "Unknown";
    }
    void init() {
        std::cout << name() << std::endl;
    }
};
class SpecificDriver : public Driver {
    virtual std::string name() const override {
        return "Specific";
    }
};

可以通过 CRTP 访问子类的类成员。

#include <iostream>
template <typename Derived>
class Driver {
public:
    void init() {
        std::cout << static_cast<Derived*>(this)->name << std::endl;
        std::cout << Derived::value << std::endl;
    }
};
class SpecificDriver : public Driver<SpecificDriver> {
public:
    std::string name = "Specific";
    static constexpr char* value = "Another specific string";
};
int main() {
    SpecificDriver g;
    g.init();
}

如果需要一个公共基类来存储这些内容,或者与正常的多态行为相结合,则可以使模板类Driver从公共基类继承。