Rob*_*Rob 111 c++ constructor coding-style overloading
拥有使用默认参数的类构造函数是一种好习惯,还是应该使用单独的重载构造函数?例如:
// Use this...
class foo
{
private:
std::string name_;
unsigned int age_;
public:
foo(const std::string& name = "", const unsigned int age = 0) :
name_(name),
age_(age)
{
...
}
};
// Or this?
class foo
{
private:
std::string name_;
unsigned int age_;
public:
foo() :
name_(""),
age_(0)
{
}
foo(const std::string& name, const unsigned int age) :
name_(name),
age_(age)
{
...
}
};
Run Code Online (Sandbox Code Playgroud)
这两个版本似乎都有用,例如:
foo f1;
foo f2("Name", 30);
Run Code Online (Sandbox Code Playgroud)
您更喜欢或推荐哪种风格?为什么?
Sam*_*kes 38
我会使用默认参数,特别是因为C++不允许链接构造函数(因此您最终必须复制初始化列表,并且可能更多,为每个重载).
也就是说,有一些带有默认参数的陷阱,包括可以内联常量的事实(从而成为类的二进制接口的一部分).另一个需要注意的是,添加默认参数可以将显式多参数构造函数转换为隐式单参数构造函数:
class Vehicle {
public:
Vehicle(int wheels, std::string name = "Mini");
};
Vehicle x = 5; // this compiles just fine... did you really want it to?
Run Code Online (Sandbox Code Playgroud)
pae*_*bal 15
此讨论既适用于构造函数,也适用于方法和函数.
好处是你不需要为每种情况重载构造函数/方法/函数:
// Header
void doSomething(int i = 25) ;
// Source
void doSomething(int i)
{
// Do something with i
}
Run Code Online (Sandbox Code Playgroud)
不好的是你必须在标题中声明你的默认值,所以你有一个隐藏的依赖:就像你更改内联函数的代码一样,如果更改标题中的默认值,则需要重新编译所有源代码使用此标头确保它们将使用新的默认值.
如果不这样做,源仍将使用旧的默认值.
好处是,如果您的函数没有内联,则可以通过选择一个函数的行为来控制源中的默认值.例如:
// Header
void doSomething() ;
void doSomething(int i) ;
// Source
void doSomething()
{
doSomething(25) ;
}
void doSomething(int i)
{
// Do something with i
}
Run Code Online (Sandbox Code Playgroud)
问题是您必须维护多个构造函数/方法/函数及其转发.
Pau*_*han 13
根据我的经验,默认参数在当时看起来很酷,让我的懒惰因素感到高兴,但随后我正在使用课程,当默认情况开始时我很惊讶.所以我真的不认为这是个好主意; 最好有一个className :: className(),然后是className :: init(arglist).只是为了可维护性的优势.
两种方法都有效。但是,如果您有一长串可选参数,请使用默认构造函数,然后让set函数返回对此的引用。然后链接设置者。
class Thingy2
{
public:
enum Color{red,gree,blue};
Thingy2();
Thingy2 & color(Color);
Color color()const;
Thingy2 & length(double);
double length()const;
Thingy2 & width(double);
double width()const;
Thingy2 & height(double);
double height()const;
Thingy2 & rotationX(double);
double rotationX()const;
Thingy2 & rotatationY(double);
double rotatationY()const;
Thingy2 & rotationZ(double);
double rotationZ()const;
}
main()
{
// gets default rotations
Thingy2 * foo=new Thingy2().color(ret)
.length(1).width(4).height(9)
// gets default color and sizes
Thingy2 * bar=new Thingy2()
.rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
// everything specified.
Thingy2 * thing=new Thingy2().color(ret)
.length(1).width(4).height(9)
.rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
}
Run Code Online (Sandbox Code Playgroud)
现在,在构造对象时,您可以选择一个显式命名要覆盖的属性和已设置的属性。更具可读性:)
同样,您不再需要记住构造函数的参数顺序。