2011-09-18 89 views
-1

如果我有以下代码(简化版本的问题):C++原型初始化列表?

class TestA 
{ 
    public: 
    int A,B,C; 

    TestA(){A = 1; B = 5; C = 10;} 
}; 

//This is a referencing class to allow for universal and consistent operations 
class TestB 
{ 
    public: 
    int &A, &B, &C; //Note references 

    TestB(TestA &A) : A(A.A), B(A.B), C(A.C){}; //This is fine 
    TestB(TestC &C) : A(C.A), B(C.B), C(C.C){}; //This needs to be prototyped 
}; 

//Similar class to TestA but in the main program would have... 
//...many different and conflicting variables and has to be treated as stand alone 
class TestC 
{ 
    public: 
    int A, B, C; 
    int Size; 

    void Function() 
    { 
     TestB B(*this); //This uses TestB. TestB cannot be prototyped. 
     //etc etc 
    } 
}; 

我想知道,是否有可能原型初始化器基于列表构造?

如果不是,有什么选择?请记住引用必须立即初始化。

+0

怎么办你的意思是“原型”?你是否指的是你需要一个单独的声明和定义,以便'TestC'可用? –

+0

你是什么意思在ctors中的“原型”初始值设定项列表? –

+0

TestC将其自身的副本传递给TestB,以便TestB可以返回到TestC。然后,TestA将自己复制到另一个TestB,允许两个类(TestA和TestC)相互操作,并传递给TestB预期功能,而不需要向下转换或向上转换(这可能涉及切片,因此存在问题)。 – SSight3

回答

1

如果“原型”你的意思是函数声明和定义的分离,这应该工作:

class TestB { 
    // ... 
    TestB(TestC &C); 
}; 

TestB::TestB(TestC &C) : A(C.A), B(C.B), C(C.C) { 
}; 
+0

非常好。谢谢你的答案。 – SSight3

+0

@Branko:虽然你忘记了前面的声明。 –

+0

@Tomalak没关系。我也是如此,但我知道它需要提前申报。我只是不知道(如何)初始化列表的原型。我意识到,一旦构造器开始访问它不可能知道的变量,就会有冲突。 – SSight3

2

如果要单独声明和定义构造函数与成员初始化器列表:

struct B;    // <-- (forward declaration of B) 
struct A { 
    A(B& b);   // <-- A ctor declaration 
    B& b; 
}; 

struct B {    // <-- (real definition of B) 
    A a; 
}; 

A::A(B& b) : b(b) {}; // <-- A ctor definition (with member-initialiser!) 

成员初始化器不胜枚举与定义,而不是声明。

+0

我认为通过原型设计他意味着在初始化程序列表中使用对象的声明。 – pmr

+0

@pmr:是的,他现在可以做,因为它的_use_已被移到其他地方,稍后在他的代码中。 –

+0

谢谢你的回答。 – SSight3

1

原来的问题已经回答了,但我还是忍不住的设计发表评论。

这3类是完全爱上彼此.. :) ..我的意思是不需要的循环依赖和紧耦合等..

为什么没有TESTC和种皮延长TESTB?

假设你有没有这样做很好的理由,另一种选择是这样的:

代码阅读评论

class TestX 
{ 
public: 
    int A,B,C; 

    TestX() 
    { 
     A = 1; 
     B = 5; 
     C = 10; 
    } 
}; 

// "int A,B,C;" coming from baseclass now. 
class TestA : public TestX {}; 

// fwd decl not needed anymore. 
// class TestC; 

class TestB 
{ 
public: 
    int &A, &B, &C; //Note references 

    // dealing with TestX instead. 
    TestB(TestX &X) : A(X.A), B(X.B), C(X.C) {}; 
}; 

class TestC : public TestX 
{ 
public: 
    // coming from baseclass now 
    // int A,B,C; 
    int Size; 

    void Function() 
    { 
     // moved out to some other place.. main() in this case. 
     // TestB B(*this); 
    } 
}; 

// not needed anymore.. 
// TestB::TestB(TestC &C): A(C.A), B(C.B), C(C.C) {} 

int main() 
{ 
    TestC c; 
    TestA a; 

    TestB bc(c); 
    TestB ba(a); 

    // your primary usecase (referencing class to allow for universal and consistent operations) 
    // is satisfied, without changing anything in the client code. 
    // You can still use c as TestC where "int Size" or "Function" are needed. 

    return 0; 
} 

现在的依赖关系是:

X <---- A 
^ |__ C 
| 
B 
+0

这是一个聪明的想法,如果我重新设计,我可能会尝试合并这个,但是我写了很多头文件,原型/设计非常糟糕(我自己的错误)。一旦我做了基本建设(工作班等),我希望提交它的设计和改进批评。 – SSight3

+0

当然..记住你总是会找到“很好的理由”,因为没有马上做正确的事情。 :) – Kashyap