在C ++中用另一个类初始化类?

时间:2009-11-10 22:34:24

标签: c++ class-design

我在头文件中有这个定义:

class Owner
{
private:
    // Fields
    Child* _myChild1;
public:
    // Constructors
    Owner();
    Owner(const char childName[]);
};

和这个实现:

Owner::Owner(const char childName[])
{
//do some operations - children must be created after these ops
_myChild = new Child(childName);
}

和这个main()函数:

int main()
{
Owner("child1"); 
}

有些问题,请在这里请耐心等待,我刚开始使用C ++ ..

  • 鉴于子类在编译时是已知的,我认为我不需要在堆上使用'new'创建它们吗?如果是这样的话?我已尝试在Owner实现中使用此语法,但编译器发出呻吟声('术语不计算函数..'):

_myChild(childName);

  • 但是,在实现中使用这种语法是可以的,为什么?

Child _myChild(childName);

  • 我使用的范例是否正确?换句话说,作为一般规则,如果一个类包装另一个类,那么所有者是否只持有指向它包装的类的指针?
  • 你会有更多有经验的人这样做吗?

感谢您的任何建议..

3 个答案:

答案 0 :(得分:5)

像这样:

class Owner
{
    private:        // Fields
        Child   _myChild1;
    public:        // Constructors
        Owner();
        Owner(const char childName[]);
};

Owner::Owner()
    :_myChild1("Default Name")
{}

Owner::Owner(const char childName[])
    :_myChild1(childName)
{}

// Without more info about what you are doing it is hard to tell
// But a trivial change could be

Owner::Owner()
// Child defautl constructor called here
{
    // Do processing.
    _myChild1.updateName(name);
}

Owner::Owner(const char childName[])
// Child defautl constructor called here
{
    // Do processing.
    _myChild1.updateName(std::string("X") + childName);
}

问题是在孩子面前你需要做什么样的处理。

作为一方不是:

  • 避免使用下划线作为成员名称中的第一个字符 大部分时间都可以,但有些情况不是。所以最好避免它们。
  • 而不是传递一个字符数组传递std :: string const&

答案 1 :(得分:4)

你在这里描述的是“组合”,其中一个类位于另一个类中。在此,Owner包含Child指针。因此,Child实例的实际分配和初始化必须在运行时的某个地方完成。

如果希望Owner包含一个Child的实例,而不必在new的堆上分配,只需将成员变量声明为:

Child _myChild1;

而不是指针。

答案 2 :(得分:3)

基本上,它是如何工作的:

  • 如果在所有者类之前完全定义了 Child 类,则可以将其全部包含在所有者中,或者作为指针,无论你喜欢什么。
  • 如果在所有者类之前没有完全定义 Child 类,则必须进行前向声明,并且只能将其作为指针包含在内。这必须使用new在堆上分配。

如果确实包含了一个完整的类,它将在构造所有者对象的同时构造。除非另有明确说明,否则编译器将使用默认构造函数。

选项1:

// will create a Child object using the default constructor.
// this is done even before doStuff() is called.

Owner::Owner(const char childName[]) {
  doStuff();
}

选项2:

// will create a Child object using the Child(const char*) constructor.
// again, done before doStuff() is called.
Owner::Owner(const char childName[]): _myChild(childName) {
  doStuff()
}

你不能在构造函数本身内使用_myChild(childName);语法,因为 _myChild 在它到达那么远之前就已经被构造了。 Child _myChild(childName);是合法的,但它会创建一个名为 _myChild 的新本地对象,而不是修改类成员 _myChild 。这可能不是预期的结果。

如果要在构建后为 _myChild 指定新值,请执行以下操作之一:

  • 首选方法:以某种方式修改现有对象(例如重载赋值运算符以允许您执行_myChild = childName;,或使用某种形式的_myChild.setName(childName);函数)。< / LI>
  • 替代方法:使用_myChild = Child(childName);创建新的子级并将其分配给成员变量。

这第二个选项尽管是功能性的,但是效率很低,因为它需要构造对象两次,没有充分的理由。