在工作中,遇到的几个关于构造函数的问题,以及语言边缘的坑(如何避开)。
显式类型转换函数和构造函数优先级?
1 2 3
| Minimal(src);
(Minimal)src;
|
会先按照构造函数解析,还是
构造函数能不能相互调用?
http://www.cppblog.com/wolf/articles/63490.html
http://www.cnblogs.com/chio/archive/2007/10/20/931043.html
传统的 func(var)
调用方式肯定不行,因为这意味着在某构造函数中又创建了个临时对象。
但通过评论中提到的方式,还是可以复用构造函数定义的:
1 2 3
| this->ClassName::ClassName() new (this)CLS(0);
|
补充一点,构造函数是可以调用的,但是调用方式是这样的: obj.ClassName::ClassName();
在构造函数内部调用是这样的: this->ClassName::ClassName()
楼主的调用方式是错误的,是在创建一个临时对象,不是调用构造函数
上述两篇帖子分别是 07/08 年的,在 c++11 中支持 定义构造函数时通过初始化列表的形式调用其他构造函数:
1 2 3 4 5
| class Foo { public: Foo(char x, int y) {} Foo(int y) : Foo('a', y) {} };
|
需要指出的是,委托构造函数的语法
在委托构造函数内,成员初始值列表只有一个唯一的入口,就是类名本身。摘自《C++ Primer(5th)》P261
以下代码编译无法通过
1 2 3 4 5 6 7 8
| class Foo { public: Foo(char x, int y): Foo(y), x_(x) {} Foo(int y) {} private: char x_; };
|
不同的默认构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <type_traits>
struct X { X() = default; };
struct Y { Y() { }; };
int main() { static_assert(std::is_trivial<X>::value, "X should be trivial"); static_assert(std::is_pod<X>::value, "X should be POD");
static_assert(!std::is_trivial<Y>::value, "Y should not be trivial"); static_assert(!std::is_pod<Y>::value, "Y should not be POD"); }
|
https://stackoverflow.com/questions/20828907/the-new-keyword-default-in-c11
Giving a user-defined constructor, even though it does nothing, makes the type not an aggregate and also not trivial.
If you want your class to be an aggregate or a trivial type (or by transitivity, a POD type), then you need to use = default
.
WTF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <cstdio>
class Test { Test() = default; public: void hello() const { printf("Hello world.\n"); } };
int main() { Test abc{}; abc.hello(); return 0; }
|
继承的构造函数
常用方式
1 2 3 4 5 6
| class Derived { Derived(int a):Base(a) {} Derived(std::string a):Base(a) {} Derived(int a, doubel b):Base(a, b) {} };
|
在 c++11 新标准中,可以简化为(是不是类似语法糖的东东?)
1 2 3 4
| class Derived { using Base::Base; // 继承 Base 的构造函数 };
|
类不能继承默认、拷贝和移动构造函数。摘自《C++ Primer(5th)》P557
无效初始化
最坑的地方,在于以下代码误将成员变量 _tick_count
绑定到了临时变量,使用时其指向垃圾值。编译不报错,运行也不崩溃,无法达到预期目的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| struct cmdlet { cmdlet(const std::string & label) : label(label), _others() { } cmdlet(const std::string & label, unsigned _tick_count) : label(label), _tick_count(_tick_count) { }
const std::string label; const unsigned & _tick_count = _others[0];
cmdlet(const cmdlet & rhs) : label(rhs.label), _others(rhs._others) {
} private: std::array<unsigned, 3> _others; };
|