[英]Base class as argument in derived class constructor in c++
I'm having trouble with constructors in derived classes. 我在派生类中遇到了构造函数的麻烦。 Lets say I have the simple code below here with one base class Base and two classes whom inherits from Base, Derived1 and Derived2.
可以说我在下面有一个简单的代码,其中有一个基类Base和两个从Base继承的类Derived1和Derived2。
I want Derived2 to hold a pointer to Base, which could point either to Base or Derived1. 我希望Derived2持有一个指向Base的指针,该指针可以指向Base或Derived1。 I cannot manage to write the constructor for this tho.
我无法为此写出构造函数。 If I pass in a Derived1 object I get a empty Base once inside the constructor.
如果传入Derived1对象,则在构造函数中会得到一个空的Base。
Class Base
{
public:
Base(int a): m_a(a)
{
}
protected:
int m_a;
};
//First derived class of base
class Derived1 : public Base
{
public:
Derived1(double c): m_c(c)
{
}
private:
double m_c;
};
//Second derived class of Base
class Derived2 : public Base
{
public:
Derived2(Base b, int k): m_b(&b), m_k(k)
{
}
private:
int m_k;
Base* m_b;
};
int main()
{
Base b(2);
Derived1 d1(3.0);
Derived2 d2(d1, 3);
Derived2 d3(b, 4);
}
You likely want to accept a Base*
in your constructor, rather than an actual Base
instance: 您可能希望在构造函数中接受
Base*
,而不是实际的Base
实例:
Derived2(Base* b, int k) : m_b(b), m_k(k)
{
}
Then you can pass the address-of the instance that you want your Derived2
instance to point to: 然后,您可以传递您希望
Derived2
实例指向的实例的地址:
Derived2 d2(&d1, 3);
Derived2 d3(&b, 4);
Note that you should give them thought to the ownership of the Base
object being pointed to in the Derived2
instances. 请注意,您应该让他们考虑在
Derived2
实例中指向的Base
对象的所有权。 Additionally, if the Derived2
object persists after the passed Base
object has been deleted, accessing m_b
will result in undefined behavior. 此外,如果在删除传递的
Base
对象之后Derived2
对象仍然存在,则访问m_b
将导致未定义的行为。 If you can use C++11, consider passing and storing std::shared_ptr<Base>
instead of a raw pointer. 如果可以使用C ++ 11,请考虑传递和存储
std::shared_ptr<Base>
而不是原始指针。
I understand that you want Derived2
to hold a pointer to another Base
object. 我了解您希望
Derived2
持有指向另一个Base
对象的指针。
First issue: your constructor uses a value argument for the base object: 第一个问题:您的构造函数对基础对象使用值参数:
Derived2(Base b, int k): m_b(&b), m_k(k)
This means that when it gets called, a temporary copy of the parameter passed for b is made, and you will store the address of this temporary object. 这意味着在调用它时,将为b传递一个参数的临时副本,然后您将存储此临时对象的地址。 Of course, once you leave the statement calling the constructor, this address gets invalid.
当然,一旦留下调用构造函数的语句,该地址将无效。 Segfault guaranteed sooner or later !
Segfault早晚保证!
Solution: pass argument by reference (rest of code unchanged): 解决方案:通过引用传递参数(其余代码不变):
Derived2(Base& b, int k): m_b(&b), m_k(k)
Second issue: Your code doesn't compile, because Base
doesn't have default constructor and the constructor for Derived1
and Derived2
do not provide for a valid Base
in their initialisation list. 第二个问题:您的代码无法编译,因为
Base
没有默认的构造函数,并且Derived1
和Derived2
的构造函数在其初始化列表中未提供有效的Base
。
Solution 1: Either provide an explicit base intialisation in ALL derived constructors. 解决方案1:在所有派生的构造函数中提供显式的基础初始化。 For example :
例如 :
Derived2(Base& b, int k) : m_b(&b), m_k(k), Base(k) // is k the right value ?
{ ... }
Solution 2: Or consider using a default value for the parameter of Base
constructor: 解决方案2:或考虑对
Base
构造函数的参数使用默认值:
Base(int a=0): m_a(a) // default parameter is 0
{ ... }
There are many problems here. 这里有很多问题。 Let's ignore the design problems with Derived2 for now (naked pointers are evil).
现在让我们忽略Derived2的设计问题(裸指针是邪恶的)。
Focussing on Derived1
... Derived1
于Derived1
...
Derived1 is derived from Base, which means it is a Base. Derived1是从Base派生的,这意味着它是 Base。 Base has only a 1-argument constructor (and therefore no default constructor)
Base只有1个参数的构造函数(因此没有默认构造函数)
Derived1 has a 1-argument constructor also, but this argument is initialising Derived1's data ( m_c
). Derived1也有一个1参数的构造函数,但是此参数正在初始化Derived1的数据(
m_c
)。
Since Derived is a Base, the Base part of it must be constructed at construction time. 由于“派生” 是基础,因此必须在构建时构建其基础部分。 Since you must construct Base, and base has only a 1-argument constructor, you must specifically mention this in the constructor of Derived1.
由于您必须构造Base,并且base只有一个1参数的构造函数,因此必须在Derived1的构造函数中特别提及。
Like this: 像这样:
class Derived1 : public Base
{
public:
Derived1(double c, int some_value_for_base)
: Base(some_value_for_base)
, m_c(c)
{
}
...
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.