{} 与 ()初始化变量
下面两种方式都把foo
和bar
初始化了10和100
//圆括号初始化
int foo(10);
int bar(100);
//花括号初始化
int foo{10};
int bar{100};
他们的区别在于花括号是C++11新引入的初始化方式,成为列表初始化 (list initialization),他们有一个区别:
long double ID = 3.1415926;
int foo{ID};//会报错,long double -> int会导致信息丢失
int bar(ID);//虽然也会导致信息丢失,但圆括号允许这样的转换
所以用花括号来说比较有限制性,很安全。
struct 和 class的区别
一般定义类可以用class
和struct
两种关键字来定义,二者仅仅是形式上的区别,唯一的不同之处在于成员的默认访问权限不一样:
//class关键字定义类
class TEST_1 {
int foo;//foo的访问权限是public
public:
int a,b;
};
//struct关键字定义类
struct TEST_2 {
int foo;//foo的访问权限是private
public:
int a,b;
};
就像上面注释所说,如果使用class
关键字定义类,那么在这个类中定义在第一个访问说明符之前的成员是private
,相反,struct
定义的类中定义在第一个访问说明符之前的成员默认是private
的。(访问说明符:public
和private
)。
类的const成员函数
const Sales_Data& displayName() const;
类似于上面这种类的成员函数后跟const
关键字的成员函数就是const成员函数。我们知道在调用成员函数时,会把当前对象的地址作为隐形的参数this
传递进去。this
是常量指针,也就是* const
的,它的值不允许改变,但它指向的值可以不是常量。这就引发了一个问题:当类的一个实例被声明成了const
,这个实例是无法调用一般的成员函数的,因为this
是* const
而不是const * const
。如果确实有必要,这时候就应该在一般函数的声明及定义结尾加上const
,这样在const
实例在调用该函数时this
会被转换成const * const
,第一个const
就是结尾加的那个const
。这时候这个成员函数就可以作用这个常量实例了。我们举个栗子:
class Foo {
public:
int bar = 100;
Foo() = default;
Foo(int bar_) : bar(bar_){};
void display_bar(){
std::cout << bar;
}
};
int main() {
Foo a;
a.display_bar();
return 0;
}
在这个栗子中,display_bar
成员函数打印出Foo
类的bar
值,没有对原对象作出任何改变。a
的调用是没有任何问题的,但是b
是const
的,调用就立马出现了问题:
'this' argument to member function 'display_bar' has type 'const Foo', but function is not marked const
。
一旦编译运行就会报错:passing 'const Foo' as 'this' argument discards qualifiers
所以为了使这个函数既适用于const
对象以及非const
对象,我们在加上const
就不会出错了。
class Foo {
public:
int bar = 100;
Foo() = default;
Foo(int bar_) : bar(bar_){};
void display_bar() const{
std::cout << bar;
}
};
int main() {
Foo a;
a.display_bar();
return 0;
}
incomplete类
类在没有定义之前,是一个不完全类型(incomplete type),所以一个类的成员不应该包含其自身类型。但是,类的成员可以包含其自身的指针或指针。
class Foo {
int a = 100;
//错,不允许类成员出现其本身类型
//Foo b;
Foo *b;//可以
}