通过区分函数是否是const,我们可以对其进行重载,因为非常量版本的函数对于常量对象是
不可用的,所以我们只能在一个常量对象上调用const成员函数,另一方面,虽然可以在非常量
对象上调用常量版本或非常量版本,但显然此时非常量版本是一个更好的匹配class firstclass { public: void show(); void show() const; }; void firstclass :: show() { std::cout << "show()" << std::endl; } void firstclass :: show() const { std::cout << "show() const" << std::endl; } int main(int argc, char** argv) { firstclass a; const firstclass b; a.show(); //show() b.show(); //show() const return 0; }
class secondclass; 这种声明方式被称为前向声明,他向程序引入了一个名字并只指明
secondclass是一个不完全类型,也就是说我们知道second是一个类类型,但是不清楚他
到底包含哪些成员,不完全类型只能在非常有限的情境下使用,可以定义指向这种类型的指针
或引用,也可以声明一不完全类型作为参数或者返回类型的函数,对一个类来说,在我们创建
它之前该类型必须被定义过,而不能仅仅被声明,否则编译器无法了解这样的对象需要多少
存储空间,类似的,类必须首先被定义,然后才能用引用或者指针访问其成员,毕竟,如果类
尚未定义,编译器也不清楚该类到底有哪些成员。class second { public: friend void show(); second(); }; second :: second() { show(); //直接这样写是错误的,因为此时show函数还没有定义 } //必须将show() 函数放到 second :: second()之前定义 void show() { std::cout << "123" << std::endl; } //下面这种写法是正确的 class second { public: friend void show(); second(); }; void show() { std::cout << "123" << std::endl; } second :: second() { show(); }
C++11表中可以使用当前类的其他构造函数初始化构造函数的重载
class third { public: third() {std::cout << "1" << std::endl;} third(int a) : third() {std::cout << "2" << std::endl;} }; 可以使用其他构造函数初始化当前构造函数, 但是必须指定C++11标准,这种构造函数称为委托构造函数。
禁止构造函数的隐式类型转换可以使用explicit关键字,但是explicit关键字只对一个实参的构造函数有效,多个实参的构造函数不能用于执行隐式转换,所以无法将这些函数定义为explicit, 声明称explicit不报错,但是不起作用。在类内声明构造函数时使用explicit关键字,在类外定义时不应该重复,否则报错
class four
{
public:
four() {}
explicit four(int a);
explicit four(int a, int b) {}
explicit four(four &a) {}
};
/*
这种写法是错误的
explicit four::four(int a)
{
std::cout << "123" << std::endl;
}
*/
four::four(int a)
{
std::cout << "123" << std::endl;
}
four a(1.0, 2.0);
//调用时创建这样的对象是可以成功的,因为进行了隐式类型转换explicit关键字没起作用
//当定义了拷贝构造函数并且指定explicit关键字 explicit four(four &a)
//则调用时:
four a(2); //编译通过
four b(a); //编译通过
four c = b; //编译不通过,
//所以不能将explicit用于拷贝形式的初始化。
- 类的静态成员函数不予任何对象绑定在一起,他们不包含this指针,作为结果,静态成员函数
不能声明为const,而且也不能在静态成员函数中使用this指针。
class five
{
public:
static void show() {std::cout << "123" << std::endl;}
//static void show2() const {} //编译会报错
};
- 静态成员可以是不完全类型,而非静态成员不能是这样, 静态成员和非静态成员的另一个区别是我们可以使用静态成员作为默认实参,非静态成员不能作为默认实参,因为他的值本身是对象的一部分,这么做的结果是无法真正提供一个对象以便从中获取成员的值,导致错误。 six a; a.show(); //输出结果a
class six
{
public:
static six a; //静态成员可以是不完全类型
six *p; //指针成员可以是不完全类型
// six x; //数据成员必须是完全类型 错误
void show(char s = str) { std::cout << s << std::endl;}
//编译报错 error: from this location
//void showa(char s = b) { std::cout << s << std::endl;}
private:
static const char str = 'a';
char b;
};