继承类使用非默认构造函数初始化自定义类
Inherited class initializing a custom made class using non-default constructor
所以我到处找,似乎找不到这个特定问题的答案。我使用的是带有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。我尝试过成员初始化方法,但编译器没有意识到受保护的变量。因此,由于一些我不知道的奇怪原因,它在这个类中找不到构造函数。即使包含对受保护成员变量(非继承)构造函数的"错误"调用,也会建议使用正确版本的构造函数。
我还不知道该怎么做。非常感谢您的帮助。
声明变量后,必须对其进行设置,否则将像函数一样调用它。
this->b = Bar(x+3);
首选的方法是使用初始值设定项列表来避免Bar
的不必要副本。但是,如果您确实需要在构造函数之外设置b,上面的例子就是如何做到这一点的。
DerFoo
的构造函数不能(也不能)初始化b
,即Foo
作业。DerFoo
的构造函数只负责初始化DerFoo
的直接子对象,即db
和作为DerFoo
基类的Foo
。Foo
的构造函数反过来负责初始化b
。
事件的顺序如下:
DerFoo
的构造函数调用Foo
的构造函数Foo
的构造函数调用b
的构造函数Foo
的构造函数运行其主体,使Foo
对象完全构造DerFoo
的构造函数调用db
的构造函数DerFoo
的构造函数运行其主体,使DerFoo
对象完全构造完成
如果在DerFoo
构造函数中,您不喜欢Foo
构造函数在b
中留下的值,则可以使用以下任何一种语法为b
分配一个新值:
b = Bar(47);
this->b = Bar(47);
this->Foo::b = Bar(47);
Foo::b = Bar(47);
我觉得这个问题不太清楚,但让我们看看我是否理解你想要做什么以及如何做。
DerFoo::DerFoo(int x) : Foo(x), [a]
db(x+3)
// db(4.0,30) [1]
// note: candidates are Bar::Bar(const Bar&), Bar::Bar(int)
// b(x-3) [2]
{
//this->b(x - 3); [3]
//this->db(x + 3); [4]
}
第一个错误是[1],编译器告诉您Bar
的构造函数不同时使用double和int。该错误还列出了您可以使用的两个可能的构造函数:Bar(int)
和Bar(Bar const &)
。我不确定你想用这条线做什么,但你已经想好了(前一行),只要提供int
,电话就可以了。
[2] b
不是DerFoo
的成员,因此不能在DerFoo
的初始化器列表中初始化。Foo
负责初始化它自己的成员,这将通过调用[a]中的Foo
构造函数来实现。
[3] ,[4],这两个表达式都采用this->member(i)
的形式。在初始化期间,语法member(i)
将很好地用i
的值初始化member
。在初始化之外,语法意味着调用operator()( int )
传递i
的值。这些成员已经初始化,但如果要重置它们,则需要分配,而不是初始化它们。
b
在Foo类中。要访问它(当然),请使用
Foo::b = Bar(x-3);
您不需要使用初始值设定项列表,在这一点上,您肯定也应该使用初始化项列表。
在构造对象时,在输入构造函数的代码之前,所有成员变量都已构造完成。如果不提供初始值设定项,它们将是默认构造的。
此外,在构造变量之后,不能再构造该变量。您的
this->b(x+3)
不是告诉编译器构造b
,而是告诉它在对象上调用一个名为b
的函数。这样的函数在您的类中不存在,因此出现了错误。请注意,一旦将对象构造为变量,就无法再次调用该变量的构造函数(只是为了更改值)。
与大多数语言一样,可以使用=
更改值。因此你可以做:
Foo::Foo(int x)
{
this->b = Bar(x+3);
}
这意味着您正在创建另一个无名称的Bar
对象,并将其值指定给this->b
。您应该知道,这意味着,在创建Foo
时,您将创建两个Bar
对象。首先是默认构造的,之前。输入构造函数代码,然后输入新的无名称代码。然后,您将最终将值分配给已经构建的对象,因此此代码比使用初始值设定项列表的代码效率低得多。
编辑:
由于我错过了上面代码中的第二个doesn't work
,这里有一些附加信息:
您还试图在派生的DerFoo
对象的构造函数中直接初始化b
。然而,一旦达到代码的这一部分,就已经构建好了。因此,任何在派生构造函数中构造它的尝试都会迟到。
因此,您必须向Foo
添加另一个构造函数,该构造函数接受该值,并在DerFoo
的构造函数中使用该值。该解决方案是优选的,因为它将只在b
中构造Bar
对象一次。如果不能添加这样的构造函数,则需要在DerFoo
的构造函数代码中使用赋值。
即使使用了作用域运算符,尝试直接在DerFoo
构造函数中初始化b
也不会起作用。
DerFoo::DerFoo() : Foo::b(x-3) {}
仍然会产生错误:http://ideone.com/6H8ZD
- 有没有一种代码密度较低的方法来使用非默认构造函数初始化数组?
- 如何在 C++ 中使用它的构造函数初始化 unique_ptrs 的 2D 向量?
- 在C++中使用默认构造函数初始化对象的不同方法
- 使用默认构造函数初始化对象的不同方法
- 我们可以用参数化构造函数初始化结构的数组吗?
- 有没有办法使用该类的构造函数初始化另一个类的私有部分内的对象数组?
- 类内初始化与构造函数初始化列表的顺序
- 通过 C++ 中的重载构造函数初始化未知类型的变量
- 使用复制构造函数初始化 new[]
- 如何从子类的构造函数初始化父类的私有成员
- 在构造函数初始化列表中使用 std::variant
- 使用构造函数初始化结构还是在之后设置其值更好?
- C++ 没有匹配的构造函数初始化 []
- 我正在使用dev c ++,但收到错误(C++98'array'必须由构造函数初始化)
- 使用所述填充构造函数初始化向量中的向量
- 如何同时创建一个具有两个或多个构造函数初始化的对象
- 在 new 关键字中,由默认构造函数初始化的类中的元素是否也使用 new 关键字在C++?
- 这是使用构造函数初始化数组对象的最佳方法吗?
- 内置类型的构造函数初始化
- 构造函数初始化和对象损坏