原来写法 | 现在写法 | 原因 |
---|---|---|
const char* const authorName=“ScottMeyers” | const std::string authorName(“Scott Meyers”) | |
#define ASPECT_RATIO 1.653 | const double AspectRatio = 1.653 | 因为宏没有计入符号表 |
class GamePlayer
{
private:
static const int NUMTurns = 5;
int socres[NumTurns];
}
此时是不能对NUMTurns取地址,如果要取地址,则要在class的cpp文件中定义const int GamePlayer::NUMTurns,为什么不能用#define呢?因为define无视作用域,当定义之后全局有效,除非是#undef,不具有封装性,NUMTurns只有在int char bool时,才能在class内部赋值!
当需要在class内部赋值时,可以用enum,枚举约等于#define,无法取地址
class GamePlayer
{
private:
enum{ NUMTurns = 5};
int socres[NumTurns];
}
一般宏定义函数为
#define CALL_WITH_MAX(a,b) f((a)>(b)?(a):(b))
可以替换为
template<class T>
inline void callWithMax(const T&a, const T&b)
{
f(a>b? a:b);
}
char greeting[] = "hello";
char* p = greeting;
const char* p = greeting; //对象常量
char* const p = greeting; // 指针常量
const char* const p = greeting; //const pointer const data
void f1(const Widget* pw);
void f2(Widger const* pw); //都是const dara
上述如果是const_iterator cIter, 那么*cIter++,运行顺序是先cIter++,然后取 *cIter,因为是对象,重载了
const修饰类中的成员函数时,表示对象是const,可以利用这个来进行函数重载
注意const对象一般是passed by reference to const或者pointer to const,那么该对象中调用的函数必须也是const的才行!
见fun2 !
class TextBox
{
private:
std::string text;
public:
TextBox(string b):text(b){};
const char& fun1(const size_t& a)const //表示TextBox对象为const,函数无法修改对象
{
cout<<text[a]<<"++1"<<endl;
return text[a];
}
char& fun1(const size_t& a) //不能仅按照返回值重载!!!
{
cout<<text[a]<<"++2"<<endl;
return text[a];
}
};
int main()
{
const TextBox text("hello");
text.fun1(1); //走的是第一个fun1
text.fun(1)不能当左值了,同时如果没有引用也不能当左值
void fun2(const TextBox& a)
{
a.fun1() //为第一个
}
特别注意的点是const成员函数可以用mutable摆动场来修饰需要更改的参数!下例子中,将text改成mutable,则可以在const函数中修改!
class TextBox
{
private:
mutable std::string text;
public:
TextBox(string b):text(b){};
const char fun1(const size_t& a)const //表示TextBox对象为const,函数无法修改对象
{
cout<<text[a]<<"++1"<<endl;
text[a] = 'p';
cout<<text[a]<<"++1"<<endl;
return text[a];
}
char fun1(const size_t& a) //不能仅按照返回值重载!!!
{
cout<<text[a]<<"++2"<<endl;
return text[a];
}
};
int main()
{
const TextBox text("hello");
text.fun1(1);
class Mesion
{
public:
Mesion(){cout<<"mesion"<<endl;}// 1
Mesion(const Mesion& xiaomeison){cout<<"Copy mesion"<<endl;} //2
Mesion& operator=(const Mesion& xiaomeison){cout<<"= mesion"<<endl;} //3
};
class Jiangx
{
public:
Mesion mesion;
Jiangx(Mesion& m):mesion(m){cout<<"Jiangx"<<endl;}
};
class JiangGZ
{
public:
Mesion mesion;
JiangGZ(Mesion& m){mesion = m;
cout<<"JiangGZ"<<endl;}
};
int main()
{
Mesion ms;
Jiangx jx(ms); //2解决内存
JiangGZ jgz(ms); //1,3
A: 类的成员变量的初始化顺序只与变量在类中的声明顺序有关,与在构造函数中的初始化列表顺序无关
B: 静态成员变量先于实例变量,父类成员变量先于子类成员变量,父类构造函数先于子类构造函数。
以下为初始化顺序:
#include
using namespace std;
class A {
public:
//我们原意是先初始化b,再用b初始化a。
//但结果可以看出,类的成员变量的初始化顺序与声明顺序有关,先初始化的a,再初始化的b。
A(int val):b(val),a(b){}
public:
int a;
int b;
};
int main(int argc, char* argv[]) {
A A1(10);
cout << A1.a << endl;
cout << A1.b << endl;
getchar();
return 0;
}