处理具有长初始化列表和多个构造函数的类?

Tho*_*Low 12 c++ constructor initialization

我有一个(对我来说)复杂的对象,有大约20个数据成员,其中许多是指向其他类的指针.所以对于构造函数,我有一个很长的,很复杂的初始化列表.该类还有十几个不同的构造函数,反映了可以创建类的各种方法.这些初始化项目中的大多数在这些不同构造函数之间没有变化.

我担心的是,我现在有一大堆复制(或大部分复制)的代码,如果我需要在类中添加一个新成员,可能无法进入每个构造函数初始化列表.

class Object 
{
    Object();
    Object(const string &Name);
    Object (const string &Name, const string &path);
    Object (const string &Name, const bool loadMetadata);
    Object (const string &Name, const string &path, const bool loadMetadata);
} 

Object::Object() :
    name(),
    parent_index (0),
    rowData (new MemoryRow()),
    objectFile (),
    rows (new MemoryColumn (object_constants::RowName, OBJECTID, object_constants::ROWS_OID)),
    cols (new MemoryColumn (object_constants::ColName, OBJECTID, object_constants::COLS_OID)),
    objectName (new MemoryColumn(object_constants::ObjName, STRING, object_constants::short_name_len, object_constants::OBJECTNAME_OID)),
    parent     (new MemoryColumn(object_constants::ParentName, STRING, object_constants::long_name_len, object_constants::PARENT_OID)),
    parentIndex (new MemoryColumn(object_constants::ParentIndex, OBJECTID, object_constants::PARENTINDEX_OID)),
    childCount (new MemoryColumn (object_constants::ChildCount, INTEGER, object_constants::CHILD_COUNT_OID)),
    childList (new MemoryColumn (object_constants::ChildList, STRING, object_constants::long_name_len, object_constants::CHILD_OID)),
    columnNames (new MemoryColumn (object_constants::ColumnNames, STRING, object_constats::short_name_len, object_constants::COLUMN_NAME)),
    columnTypes (new MemoryColumn (object_constants::ColumnTypes, INTEGER, object_constants::COLUMN_TYPE)),
    columnSizes (new MemoryColumn (object_constants::ColumnSizes, INTEGER, object_constants::COLUMN_SIZE))
{}
Run Code Online (Sandbox Code Playgroud)

然后如上所述重复其他构造函数.是否有任何智能方法为此使用默认构造函数,然后修改其他构造函数的结果?

vee*_*efu 14

如何将公共字段重构为基类.基类的默认构造函数将处理大量默认字段的初始化.看起来像这样:

class BaseClass {
    public:
    BaseClass();
};

class Object : public BaseClass
{
    Object();
    Object(const string &Name);
    Object (const string &Name, const string &path);
    Object (const string &Name, const bool loadMetadata);
    Object (const string &Name, const string &path, const bool loadMetadata);
};

BaseClass::BaseClass() :
    parent_index (0),
    rowData (new MemoryRow()),
    objectFile (),
    rows (new MemoryColumn (object_constants::RowName, OBJECTID, object_constants::ROWS_OID)),
    cols (new MemoryColumn (object_constants::ColName, OBJECTID, object_constants::COLS_OID)),
    objectName (new MemoryColumn(object_constants::ObjName, STRING, object_constants::short_name_len, object_constants::OBJECTNAME_OID)),
    parent     (new MemoryColumn(object_constants::ParentName, STRING, object_constants::long_name_len, object_constants::PARENT_OID)),
    parentIndex (new MemoryColumn(object_constants::ParentIndex, OBJECTID, object_constants::PARENTINDEX_OID)),
    childCount (new MemoryColumn (object_constants::ChildCount, INTEGER, object_constants::CHILD_COUNT_OID)),
    childList (new MemoryColumn (object_constants::ChildList, STRING, object_constants::long_name_len, object_constants::CHILD_OID)),
    columnNames (new MemoryColumn (object_constants::ColumnNames, STRING, object_constats::short_name_len, object_constants::COLUMN_NAME)),
    columnTypes (new MemoryColumn (object_constants::ColumnTypes, INTEGER, object_constants::COLUMN_TYPE)),
    columnSizes (new MemoryColumn (object_constants::ColumnSizes, INTEGER, object_constants::COLUMN_SIZE))
{}
Run Code Online (Sandbox Code Playgroud)

您的对象构造函数应该看起来更易于管理,现在:

Object::Object() : BaseClass() {}
Object::Object (const string &Name): BaseClass(), name(Name) {}
Object::Object (const string &Name, const string &path): BaseClass(), name(Name), path_(path){}
Object::Object (const string &Name, const bool loadMetadata): BaseClass(), name(Name){}
Object::Object (const string &Name, const string &path, const bool loadMetadata): BaseClass(), path_(path) {}
Run Code Online (Sandbox Code Playgroud)

与Iraimbilanja的答案在本质上类似,但避免添加内部类来访问数据,这可能会影响许多现有代码.但是,如果您已经有了类层次结构,则可能很难将其分解为基类.

  • 可能想要使用私有继承,因为这是一个实现细节. (3认同)

Kni*_*chi 11

现在几年后我们有C++ 11.如果你可以在你的项目中使用它,你有两个选择:

当公共初始化值仅在运行时已知时,您可以使用委托构造函数,这意味着一个构造函数调用另一个构造函数.

 // function that gives us the init value at runtime.
 int getInitValue();

 class Foo
 {
     const int constant;
     int userSet;

 public:
     // initialize long member list with runtime values
     Foo() 
       : constant(getInitValue())
       , userSet(getInitValue())
     {}

     // other constructors with arguments
     Foo( int userSetArg) 
       : Foo()
     {
        userSet = userSetArg;
     }
 };
Run Code Online (Sandbox Code Playgroud)

或者,如果在编译时已知其值,则可以直接在类定义中初始化成员.

class Foo
{
    const int constant = 0;
    int userSet = 0;

public:
    Foo( int userSetArg) : userSet(userSetArg){}
}
Run Code Online (Sandbox Code Playgroud)


小智 5

是的,这是可能的.
为简单起见,我假装原始代码是:

class Foo {
public:
    Foo() : a(0), b(1), x() { }
    Foo(int x) : a(0), b(1), x(x) { }

    int get_a() const { return a; }
    int get_b() const { return b; }
    int get_x() const { return x; }
private:
    int a, b, x;
};
Run Code Online (Sandbox Code Playgroud)

然后,重构的代码是:

class Foo {
public:
    Foo() : x() { }
    Foo(int x) : x(x) { }

    int get_a() const { return common.a; }
    int get_b() const { return common.b; }
    int get_x() const { return x; }
private:
    struct Common {
        Common() : a(0), b(1) { }
        int a, b;
    } common;
    int x;
};
Run Code Online (Sandbox Code Playgroud)