C ++为所有派生类初始化抽象基类受保护成员

Posted

技术标签:

【中文标题】C ++为所有派生类初始化抽象基类受保护成员【英文标题】:C++ Initialize abstract base class protected member for all derived classes 【发布时间】:2015-12-23 13:46:00 【问题描述】:

是否可以为所有派生对象初始化抽象基类的受保护成员,而无需在所有派生类构造函数中编写相同的初始化列表?这样它就像所有派生对象的静态成员一样。我想要的是这样的(除了它不起作用)像伪代码一样阅读它:

啊.h

class A 
public:
    A(string fn);
    virtual ~A();
    virtual void open_file() = 0;
protected:
    string fileName;
;

A.cpp

A::A(string fn) : fileName fn  //Initializer list is written only once here
A::~A() 

B.h

class B : public A 
public:
    B();
    ~B();

    void open_file() const override;
;

B.cpp

B::B()  //No initializer list for A::fileName here
void B::open_file() const 
    ifstream SomeFile(fileName); //Use base class' protected member
    ..... //Do some stuff with open file

想象一下还有一个C 派生类,这里没有A 的初始化列表,它有一个不同的覆盖open_file 函数..

main.cpp

string fname = "foo.txt";
A* APtr = new B(fname); //This initializes A's fileName for all derived objects as "foo.txt"
Aptr->open_file(); //B opens foo.txt
fname = "bar.txt";
A* A2Ptr = new C(fname); //Now fileName that both B and C consume is changed to "bar.txt"
A2Ptr->open_file(); //C opens bar.txt
APtr->open_file(); //B now opens bar.txt

【问题讨论】:

1.您显示的代码中没有一个 protected 成员。 2.不清楚你想达到什么。您在new B 中传递了一个参数,但B 的构造函数没有参数。你能澄清一下你到底在追求什么吗?您是否希望所有Bs 都具有相同的fileName 值?如果是这样,这个值在编译时是否已知? 我给出的示例代码就像一个伪代码,我知道它不起作用。我希望派生类对象使用的所有fileName 数据都被派生类的每个实例化更改,无论它们是BC 类型。 我还是不太明白你的目标。你能解释一下为什么让fileName 成为A 的静态保护成员不是你想要的吗? 是的,也许这就是我想要的,但我怎样才能做到这一点,以便我只为 fileName 编写一个初始化列表来管理所有派生对象。与上面的示例假想代码一样,当我将A* 实例化为B 并将fileName 发送到构造函数时,全局fileName 将被更改为B 的其他实例或C 对象。 【参考方案1】:

    你从 B:B(); deklared 构造函数,但你尝试使用它A* APtr = new B(fname); 所以编译器找不到任何匹配的构造函数。

    为所有派生对象初始化抽象基类的受保护成员,而不在所有派生类中编写相同的初始化列表

    为什么不呢?

A.hpp

class A
    
    public:
       A( string fn = "") : fileName(fn) // you can give an default path if prefered.
    ;

B.hpp

class B : public A

public:
   B( string fn = "") : A( fn )   //c++11 feature: call base constructor.

    其他可能的解决方案是: 全局变量(肮脏且不安全!-请不要这样做。) A中的静态变量。但是你只能同时打开一个文件。 为文件名提供一个 setter 和 getter。并以这种方式使用它:

main.cpp

B* b = new B();
b->setFileName("foo.txt");
b->openFile();

【讨论】:

此选项:“A中的静态变量。但你只能同时打开一个文件。”我不明白你的意思。 另外,如果我使用 setter-getter,所有派生对象都可以使用相同的 fileName 吗? 你必须决定你想要什么。 - 如果您想为所有派生对象使用相同的变量。您只能打开 1 个文件。如果我查看您的 main.cpp 示例,您会从 b 和 c 创建对象。这并不像你想要的那么容易。 2. 不,只有一个对象。但我现在不是你真正想要归档的东西。尽可能准确地描述您想要的行为。

以上是关于C ++为所有派生类初始化抽象基类受保护成员的主要内容,如果未能解决你的问题,请参考以下文章

[c++]第五章概念题 | 继承

派生类 C++ 中基类受保护成员的访问声明为公共的

回顾C++:访问权限控制之 公有保护私有继承用法详解与总结

指向派生对象的基类指针的 C++ 排序容器

类型兼容规则

继承及其应用