【发布时间】:2012-03-29 15:32:36
【问题描述】:
所以我到处搜索,似乎找不到这个特定问题的答案。我正在使用带有 cygwin 和 gcc 3.4.4 cygming special 的 winXP。
问题: 我有一个类作为接口工作,其中包含一些抽象方法和受保护的变量,这些变量应该存在于从该类继承的每个类中。现在我还有另一个类是这个接口的成员变量。
class Bar {
private:
int y;
public:
Bar(int why);
};
Bar::Bar(int why) : y(why) {}
class Foo {
protected:
Bar b;
public:
Foo(int x);
virtual void print_base();
};
Foo::Foo(int x) : b(x+3) // Have to use initializer list here.
{
//this->b(x+3); // doesn't work
}
class DerFoo : public Foo {
protected:
Bar db;
public:
DerFoo(int x);
};
DerFoo::DerFoo(int x) : Foo(x),
db(x+3) // (Bar)(int) being called, works fine
// db(4.0, 30) // no matching function for call to Bar::Bar(double, int)
// note: candidates are Bar::Bar(const Bar&), Bar::Bar(int)
// b(x-3) // doesn't work class DerFoo does not have any field named 'b'
{
//this->b(x - 3); // Doesn't work, error no match for call to (Bar)(int)
//this->db(x + 3); // Doesn't work, error no match for call to (Bar)(int)
}
所以你看到的问题是在派生的 foo 类内部,DerFoo 如何初始化 b。我已经尝试过成员初始化方法,但是编译器没有意识到受保护的变量。那么由于我不知道的一些奇怪的原因,它在这个类中找不到构造函数。即使包含对受保护成员变量(非继承)的构造函数的“错误”调用,它也会建议构造函数的正确版本。
我仍然不知道如何做到这一点。非常感谢任何帮助。
【问题讨论】:
-
我很困惑 - 通过一些小的调整,这在 ideone (ideone.com/2cLUa) 上编译得很好。您遇到了什么错误,在哪里?
-
好的,我想我知道你在哪里弄糊涂了。在您发布的代码中,
Foo::b成员变量 is 在您调用Foo(x)时被初始化。您可以向Bar构造函数添加调试消息,您会看到它被初始化了两次——一次用于b,一次用于db。一旦b被初始化,你就不能重新初始化,你必须使用=(赋值运算符)给它分配一个新的值。 -
对。感谢大家的回答,非常有见地和乐于助人。由于有人认为这是“非常低效的”,因此我的真实代码在接口级别有很多变量。这对我来说可能是一个糟糕的设计,但我认为这对这个项目并不重要。所以我想我会选择这个选择,
Foo(int b, int c, double d)...用于我的所有成员变量,然后做DerFoo(int derA, derX) : Foo (b,c,d) { ... -
@tomasgudm:还有另一种方法可以让您的代码更高效:在您的情况下,您将数据从调用代码传递到
DerFoos 构造函数到Foos 构造函数到 @987654334 @s 构造函数,然后使用它来构造实际对象。这意味着您的数据在使用之前会经过三层。如果您直接在DerFoo构造函数中创建Bar对象,将其传递给Foo构造函数,然后将std::moveit (C++11) 传递给b字段,您将有效降低分层和参数数量,同时保持高效。
标签: c++ inheritance member-variables