2008-12-17 13 views
2

我想实现这样的:现在如何将方法结果作为参数传递给C++中的基类构造函数?

class Base 
{ 
    public: 

    Base(string S) 
    { 
    ... 
    }; 
} 

class Derived: Base 
{ 
public: 
    int foo; 
    string bar() 
    { 
    return stringof(foo); // actually, something more complex 
    }; 

    Derived(int f) : foo(f), Base(bar()) 
    { 
    }; 
} 

,这不工作,我想,是因为巴()被调用派生构造函数foo的初始化之前。

我认为添加一个类似bar()的静态函数,它将foo作为参数 - 并在初始化列表中使用它,但我想问问是否还有其他技术可以用来挖掘自己这一个...

编辑:感谢您的反馈 - 这是我将如何处理静态功能。不知道如果静态和非静态函数之间的过载是太聪明了,但是......

class Derived: Base 
{ 
public: 
    int foo; 

    static string bar(int f) 
    { 
    return stringof(f); // actually, something more complex 
    } 

    string bar() 
    { 
    return bar(foo); 
    }; 

    Derived(int f) : Base(bar(f)) , foo(f) 
    { 
    }; 
} 

回答

4

是,使用函数(静态类方法或常规功能),其采用作为参数,返回一个字符串是个很好的解决方案你可以从Derived :: bar调用这个相同的函数来防止代码重复。所以,你的构造是这样的:

Derived(int f) : Base(stringof(f)), foo(f) {} 

我第一次发出呼叫的基本构造在列表中强调其中初始化发生的顺序。初始化程序列表的排序没有效果,因为所有类成员都按照它们在类体中声明的顺序进行了初始化。

这是一个非常干净的,functional方法的问题。但是,如果你还是想权衡替代品则可以考虑使用composition,而不是继承的派生和基类之间的关系:

class Base { 
public: 
    Base(string S) { ... } 
    void bat() { ... } 
}; 

class Derived { 
    Base *base; 
    int foo; 

public: 
    Derived(int f) : base(NULL), foo(f) { 
     base = new Base(bar()); 
    } 
    ~Derived() { 
     delete base; 
    } 

    string bar() { 
     return stringof(foo); // actually, something more complex 
    } 

    void bat() { 
     base->bat(); 
    } 
}; 

您需要考虑pros和缺点您的具体情况。通过派生参考Base,您可以更好地控制初始化顺序。

+0

HMM这与平普尔成语组合将是很好 – 2008-12-17 17:36:42

+0

尼斯 - 然而的组合物中的缺点是,以暴露基方法需要“蝙蝠状”存根的数目。 – Roddy 2008-12-17 19:26:43

+0

真的!我想你会因为这个原因而坚持计划A. – 2008-12-17 21:10:45

0

我一直想要这样做,但我最终放弃了。
任何合适的函数调用都可以用作Base()的参数。
另一种选择是向Base添加和替代构造函数,它接受一个int并将其转换为“string”本身。

+0

“替代构造函数”并不好,因为转换逻辑基本上是派生类的一部分。 – Roddy 2008-12-17 16:53:57

4

您只能在初始化程序列表中调用静态函数。你在代码中的方式:

class Derived: Base 
{ 
public: 
    int foo; 
    string bar() 
    { 
    return stringof(foo); // actually, something more complex 
    }; 

    Derived(int f) : foo(f), Base(bar()) 
    { 
    }; 
} 

仍然会初始化Base,然后是foo。在构造函数初始值设定项列表中写入内容的顺序无论如何不重要。它总是构建顺序:

  1. 首先,所有的虚基类
  2. 然后在它们出现在基类列表
  3. 然后在所有成员对象的顺序非虚基类它们是在类定义中定义的。

因此,您最终会以未初始化的值调用stringof。此问题已在boost::base_from_member中解决。还要注意,在所有基类的所有构造函数初始值设定项完成之前调用任何非静态成员函数都是未定义行为。

调用静态函数,但是,完全是罚款:

class Derived: Base 
{ 
public: 
    int foo; 
    static string bar(int f) 
    { 
    return stringof(f); // actually, something more complex 
    }; 

    Derived(int f) : Base(bar(f)), foo(f) 
    { 
    }; 
} 
2

的基类的构造函数总是被初始化派生类的其他成员之前调用;你的编译器应该给你一个警告,让初始化器的顺序错误。唯一正确的解决方案是让bar()这需要f作为参数的静态方法。

1

的构造为,井,构建对象。这意味着,直到它返回时,那里没有对象,因此调用成员函数不会可靠工作。正如其他人所说,使用静态函数或非成员函数。

0

只需将构造代码的初始化()函数,从构造函数中调用它。这比静态/非静态重写或类似的更简单。

相关问题