2012-10-11 113 views
2

我有一个巨大的C++代码库我正在使用。如何在C++中实例化一个成员变量中的子类实例?

我想介绍一个新的子类,并将其用于各种不同的上下文中,但是我的Java训练思想在C++中遇到了问题。

我希望尽量减少代码更改。所以,我感兴趣的主要类(下面的BAR)具有类FOO的成员变量。我想制作FOO的子类别FOOSUBCLASS。在java中这是微不足道的。对象默认通过引用存储。这段代码没有这样做(如下所示),我可以在不改变接口的情况下按摩这些代码(并且不需要引入引用)并且仍然可以让我的应用程序工作?

class FOO { 
}; 

class FOOSUBCLASS : FOO { 
public: 
    FOOSUBCLASS(const int id) {_id = id;} 
private: 
    int _id; 
}; 

class BAR { 
public: 
    BAR(const FOO foo) { _foo = foo;} 
private: 
    FOO _foo; 
}; 

下面,是我的主:

FOOSUBCLASS fsc(1); 
BAR b(fsc); 

但是,这并不在VS2005编译。它说:

“类型转换”:从“FOOSUBCLASS *”到“常量FOO &”存在转换,但不能访问

获取相同的编译错误,如果我明显的其它构造函数添加到BAR

BAR(const FOOSUBCLASS foo) { _foo = foo;} 

我对C++的理解是,它会将FOOSUBCLASS中的数据复制到类FOO的对象中。 (使用赋值运算符或类的重写版本)但在我的情况下,我在FOOSUBCLASS(和一些重写的​​成员函数)中有额外的成员变量,所以我只是不希望它做到这一点。我希望我的成员变量_foo在某些情况下属于FOOSUBCLASS类型,在其他情况下为FOO。这甚至有可能吗?

感谢您的想法。

+0

'并且没有介绍参考文献'为什么? –

+0

@JesseGood,因为我想避免在代码库中做出巨大的改变。这是一百万行代码库,引入引用将改变应用程序的生命周期管理。但是,根据下面的答案,它看起来像我完全坚持必须这样做...... – John

+0

唯一的另一种选择是添加另一个成员'FOOSUBCLASS myfoosub;'和'BAR(const FOOSUBCLASS)'构造函数。 –

回答

2

你不能像你现在写的那样去做,对不起。这被称为“切片”,关于它的更多信息可以在这里找到:What is object slicing?

如果你想要你的_foo成员是多态的,你需要使用一个指针或引用。当你做这样的事情时,要留意终身管理。

2

使基类公共

class FOOSUBCLASS : public FOO { 
public: 
    FOOSUBCLASS(const int id) {_id = id;} 
private: 
    int _id; 
}; 

而且,当心BAR构造

分配切片的指针/参考,以避免:

class FOO 
{ 
}; 

class FOOSUBCLASS : public FOO 
{ 
public: 
    FOOSUBCLASS(const int id) : _id(id) {} 
private: 
    int _id; 
}; 

class BAR 
{ 
public: 
    BAR(const FOO& foo) : _foo(foo) 
    { 
    } 
private: 
    FOO& _foo; 
}; 

注:我使用的初始化 - 列表语法,而不是构造函数体中的赋值。

+0

关于公共FOO的发现很微妙! – bobestm

+0

公众FOO让它编译,但不处理切片问题,我现在认识到这是“真正”的问题。 – John

+0

@Huh。我的代码示例处理?我想我发布了这个“12分钟前”:) :) – sehe

0

对用户来说sehe,考虑传递一个引用而不是传值给BAR的构造函数。

class BAR { public: BAR(const FOO& foo) { _foo = foo;} private: const FOO& _foo; };

1

在C首先在默认情况下使用private ++类从它们的基类继承,这意味着FOOSUBCLASSFOO但转换为内部,而不是给你访问。所以先转换class FOOSUBCLASS : FOOclass FOOSUBCLASS : public FOO和第二个是Java中的每个这是引用,所以你可以说

FOOSUBCLASS fs; 
FOO f = fs; 

但在C++中,我们有引用和非引用和使用FOO f创建非基准,实际上是一个对象, FOO f = fs只复制FOO部分fsf并且不会导致FOO参考FOOSUBCLASS来实现这一点,您应该使用指针或引用或智能指针。例如,您可以说:

FOOSUBCLASS* fs = new FOOSUBCLASS; 
FOO* f = fs; // Use pointer is OK 
FOO& rf = fs; // A reference of fs as a FOO 
std::auto_ptr<FOO> spf(fs); // OK, but for this destructor must be virtual 
相关问题