//静态static局部对象只构造一次
#include "stdafx.h"
#include <iostream>
using namespacestd;
class A
{
public:
A()
{
cout<<"CONSTRUCTION."<<endl;
}
};
void fn(int i)
{
static Aa; //static
cout<<i<<endl;
}
int main()
{
fn(12);
fn(14);
fn(16);
system("pause");
return 0;
}
所谓临时对象,就一种无名对象,它的出现如果不在程序员的预期之下,往往会造成效率上发负担。但有时候刻意制造一些临时对象,却又可以使程序干净清爽。刻意制造临时对象的方法是,在型别名称之后直接加上一对小括号,并可指定初值,例如Shape(3,5),int(8),其意义相当于调用相应的constructor且不指定对象名称。STL最常将此技巧引用于仿函数与算法的搭配上。
静态常量数据成员在类内部直接初始化。如果类内含有const static int data member,那么根据C++标准规格,我们可以直接在类内部直接给与赋值,所谓int泛指所有整型类别,不单只是int,还可以是long, short, char等。
#include <iostream>
using namespacestd;
class A
{
public:
//static 和const成员也遵循访问控制,若想在类外访问,则必须为public
const staticint a=3;
const staticlong intb=45L;
const staticchar c='C';
};
int main()
{
cout<<A::a<<endl
<<A::b<<endl
<<A::c<<endl;
system("pause");
return 0;
}
注意:const成员必须在构造函数成员初始化列表中初始化,而static必须在类外初始化。而conststatic int型可以在类内初始化,但是必须也同时在.cpp文件中定义。
//a.h
#ifndef _A_CLASS_H
#define _A_CLASS_H
#include <iostream>
using namespacestd;
class A
{
private:
conststaticint xp=23;
public:
void display();
};
#endif
//a.cpp
#include "a.h"
#include <iostream>
using namespacestd;
constint A::xp;
void A::display()
{
cout<<A::xp<<endl;
}
//main.cpp
#include "a.h"
#include <iostream>
using namespacestd;
int main()
{
A a;
a.display();
system("pause");
return 0;
}
初始化 const 成员和引用类型成员
初始化const成员和引用类型成员的问题,在教材中讲述初始化列表的章节应该都有讲过。
初始化static const成员,也就是全局的静态常量,这个用到的情况比较多,想必大家都会。通常就是在类的定义中申明staticconst成员,然后在实现文件中赋予初始值,比如:
/* (#) Test.h*/
#pragma once
class Test
{
public:
static constint MASK;//申明int 型的MASK常量
};
/* (#)Test.cpp */
#include "Test.h"
// 定义Test::MASK常量,注意这里不需要static关键字
const intTest::MASK =0xFFFF;
虽然这种static const的情况使用得最多,但有时候也会想用非static,却是const的情况。staticconst定义的常量是全局的,对该类的每一个实例(对象)甚至在全局范围都有效,而且一致。便有时候需要的常量是针对每一个实例的,每个实例都可能有同类型但不同值的常量,这时候就要用到非static,但是const的申明,如
class Test
{
public:
const intMY_MASK;
};
这种情况下,要在实例文件中像初始化static const常量一样,对其进行初始化是行不通的。
const int Test::MY_MASK = 0xFF; // 这样会报重定义错误
况且,就算编译能通过,也不能达到我们要求的“每个对象自己的常量”的要求。
正确的初始化是通过构造函数的初始化列表来进行,如:
class Test
{
public:
const intMY_MASK;
Test() : MY_MASK(0xff) {}
};
如果不是在初始化列表中对const常量进行初始化,而是在构造函数中对其赋值的话,是不成功的。很简单的道理:不能给const成员初始化。同样的道理,如果要初始化一个引用类型的成员变量,也不能在构造函数体内赋值,而只能在构造函数的初始化列表中进行初始化。
示例程序:
#include <iostream>
using namespacestd;
class A
{
private:
int num;
int &rnum; //引用
const intcnum; //const
public:
A(int);
void display();
};
A::A(int n):num(n),rnum(num),cnum(num){}
void A::display()
{
cout<<num<<endl
<<rnum<<endl
<<cnum<<endl;
}
int main()
{
A a(3);
a.display();
return 0;
}
#include <iostream>
using namespace std;
/* 引用本身不是一个对象,因此不能定义指向引用的指针,但指针是对象,所以存在对指针的引用 */
void func(int *&ptri)
{
*ptri = 123;
}
/* const引用 */
void func2()
{
const int iConst = 123;
/* 错误:一定要用const的引用指向const常亮,否则就意味着iRefConstError可能会修改该值 */
//int &iRefConstError = iConst;
const int &iRefConst = iConst;
cout << "iRefConst == " << iRefConst << endl;
}
/* 一旦定义了引用,就无法令其再绑定到另外的对象,之后每次使用这个引用都是访问它最初绑定的那个对象 */
int main()
{
int i = 23;
int &refi1 = i;
cout << "i == " << i << endl;
cout << "refi1 == " << refi1 << endl;
int &refi2 = i;
cout << "refi2 == " << refi2 << endl;
refi2 = 345;
cout << "i == " << i << endl;
cout << "refi1 == " << refi1 << endl;
cout << "refi2 == " << refi2 << endl;
int iTest = 90;
int *piTest = &iTest;
//func(&iTest); //编译错误,原因未知
func(piTest);
cout << "iTest == " << iTest << endl;
func2();
system("pause");
return 0;
}
/* 成员函数通过一个名为this的额外的隐式参数来访问调用它的那个对象,当我们调用一个成员函数时,用请求该函数的对象地址初始化this
常量对象,以及常量对象的引用或指针都只能调用常量成员函数。
只有当类没有声明任何构造函数时,编译器才会自动地生成默认构造函数
不接受任何实参的构造函数,称为默认构造函数
*/