一、const对象和const函数
1.1概念
const对象就是在对象类型上加了const修饰,如:
const Date date;
const函数是针对成员函数的,可以在成员函数上加const修饰
const函数样例:
class A{
public:
void show()const{//const函数
}
void show(){//非const函数
}
};
1.2 const函数相关知识点一
const函数和非const函数可以形成重载关系。
非const对象优先调用非const函数,没有非const函数则选择
const函数。
const对象只能调用const函数。
程序举例:
#include <iostream>
using namespace std;
class A {
public :
void show ( ) {
cout << "show()" << endl;
}
void show ( ) const {
cout << "show() const" << endl;
}
A ( ) {
}
} ;
int main ( ) {
A a;
a. show ( ) ;
const A b;
b. show ( ) ;
}
1.3 const函数相关知识点二
const函数不能对成员变量修改(只能读),也不能调用
非const函数。
非const函数可以调用const函数。
如果你非要在const函数中修改成员变量,可以使用mutable。
程序举例:
#include <iostream>
using namespace std;
class A {
int x;
public :
void funx ( ) {
cout << "x=" << x << endl;
}
void show ( ) const {
cout << "x=" << x << endl;
}
A ( ) {
x = 100 ; }
} ;
int main ( ) {
const A b;
b. show ( ) ;
}
二、拷贝构造函数
2.1概念
如果我们不提供 拷贝构造函数,则系统会提供一个默认的拷贝
构造函数。
拷贝构造函数目的是复制对象。
语法为:
类型名(const 类型名& par){
}
2.2拷贝构造函数的调用时机
时机一:使用同类型的对象创建另外一个对象时。
如:
A a;
A b=a;
如果自己提供拷贝构造函数,则需要自己完成数据的复制。
#include <iostream>
using namespace std;
struct Date{
int year;
int month;
int day;
public :
Date ( int year= 2014 , int month= 1 , int day= 1 ) {
cout << "Date(int,int,int)" << endl;
this - > year= year;
this - > month= month;
this - > day= day;
}
Date ( const Date& date) {
cout << "Date(const,Date&)" << endl;
year = date. year;
month = date. month;
day = date. day;
}
void show ( ) {
cout << year << "-" << month << "-"
<< day << endl;
}
} ;
int main ( ) {
Date datea;
datea. show ( ) ;
Date dateb= datea;
dateb. show ( ) ;
}
时机二:对象作为函数参数的值传递时
程序举例:
(在上例的基础上增加了showDate())
#include <iostream>
using namespace std;
struct Date{
. . . . . .
Date ( const Date& date) {
cout << "Date(const,Date&)" << endl;
. . . . .
}
. . . . . .
} ;
void showDate ( Date date) {
}
int main ( ) {
Date datea;
Date dateb= datea;
showDate ( dateb) ;
}
时机三:把对象作为函数的返回值时
#include <iostream>
using namespace std;
struct Date{
. . . . . .
Date ( const Date& date) {
cout << "Date(const,Date&)" << endl;
. . . . . .
}
void show ( ) const {
cout << year << "-" << month << "-"
<< day << endl;
}
} ;
void showDate ( const Date& date) {
}
const Date& processDate ( const Date& date) {
return date;
}
int main ( ) {
Date datea;
const Date dateb= datea;
showDate ( dateb) ;
processDate ( dateb) ;
}
2.3为什么要自定义拷贝构造函数
答:要自己处理对象数据复制的过程;
当我们需要对象和对象之间都有自己独立的内存(有指针或者引用
类型成员时);
2.4一个例子(自己设计一个数组)
#include <iostream>
using namespace std;
class Array {
int size;
int len;
int * datas;
public :
Array ( int len = 5 ) : size ( 0 ) , len ( len) {
datas = new int [ len] ;
}
~ Array ( ) {
delete [ ] datas;
datas = NULL ;
}
Array ( const Array& a) {
cout << "Array(Array&)" << endl;
size= a. size;
len = a. len;
datas = new int [ len] ;
for ( int i= 0 ; i< size; i++ ) {
datas[ i] = a. datas[ i] ;
}
}
void push_back ( int da) {
if ( size >= len) {
throw "out of range index" ;
}
datas[ size++ ] = da;
}
void show ( ) {
if ( size == 0 ) {
cout << "[]" << endl;
return ;
}
cout << "[" ;
for ( int i = 0 ; i< size- 1 ; i++ ) {
cout << datas[ i] << "," ;
}
cout << datas[ size- 1 ] << "]" << endl;
}
} ;
void foo ( ) {
Array arra;
arra. push_back ( 9 ) ;
arra. push_back ( 5 ) ;
arra. push_back ( 2 ) ;
arra. push_back ( 7 ) ;
Array arrb = arra;
arrb. show ( ) ;
}
int main ( ) {
foo ( ) ;
}
三、静态成员
3.1静态成员变量
如下面的name和age都属于对象级别的数据
class Person{
string name;
int age;
static int pcount;
};
而静态数据属于整个类型级别的数据,数据只有一份,举个例子比如:
统计上面这个Person一种有多少个人,即上面的pcount,每定义
一个对象(即多一个人),pcount就加一。
pcount虽然在Person中,但其不属于类,其是static,无
论你Person有多少个对象(人),pcount只有一份,其在全局区。
静态成员类似于全局变量,受类型作用域显限制和权限限制。
静态成员变量必须在类外进行初始化。
程序举例:
#include <iostream>
using namespace std;
class Person {
private :
string name;
int age;
public :
static int pcount;
Person ( ) {
pcount++ ;
}
Person ( const Person& p) {
pcount++ ;
}
} ;
int Person:: pcount= 0 ;
int main ( ) {
cout << sizeof ( Person) << endl;
cout << Person:: pcount << endl;
Person p1;
Person p2;
Person p3= p1;
cout << Person:: pcount << endl;
cout << p1. pcount << endl;
}
3.2静态成员函数
属于整个类型的函数、不使用对象就可以直接调用的函数。
静态成员函数没有this指针。
静态成员函数不能只直接访问非静态成员,但可以间接访问。
程序举例:
#include <iostream>
using namespace std;
class A {
int x;
public :
void show ( ) {
cout << "show()" << x << endl;
}
static void showa1 ( ) {
}
static void showa ( A* mythis) {
cout << "showa()" << mythis- > x << endl;
}
} ;
int main ( ) {
A a;
A:: showa1 ( ) ;
A:: showa ( & a) ;
}
3.3 写一个单例模式
单例模式即在一个进程中,这个类型对象只有一份。比如,在win10按了
按了很多次Ctrl+Alt+Del,仅出现一个任务管理器,这就是单例模式
而你在win10上可以打开很多个文件资源管理器窗口,这就不是单例模式
代码如下:
#include <iostream>
using namespace std;
class Singleton {
private :
Singleton ( ) {
}
Singleton ( const Singleton& s) {
}
static Singleton sig;
public :
static Singleton& getInstance ( ) {
return sig;
}
} ;
Singleton Singleton:: sig;
int main ( ) {
Singleton& siga= Singleton:: getInstance ( ) ;
Singleton& sigb= Singleton:: getInstance ( ) ;
Singleton& sigc= Singleton:: getInstance ( ) ;
cout << & siga << endl;
cout << & sigb << endl;
cout << & sigc << endl;
}
四、成员指针
4.1成员变量指针
4.1.1概念
指向成员变量的指针
4.1.2语法
struct Date{
int year;
int month;
int day;
};
/*定义成员变量指针*/
int Date::*pmer;
/*赋值*/
pmer=&Date::month;//要取地址
/*调用*/
Date date={2014,6,7};
date.*pmer;//值为6
Date *date2 = new Date();
date2->*pmer;
4.1.3程序举例
#include <iostream>
using namespace std;
struct Date{
int year;
int month;
int day;
Date ( int year= 2014 , int month= 6 , int day= 7 ) : year ( year) ,
month ( month) , day ( day) {
}
} ;
int main ( ) {
int Date:: * pmer;
pmer= & Date:: month;
Date date;
cout << date. * pmer << endl;
pmer= & Date:: year;
cout << date. * pmer << endl;
Date * date2 = new Date ( 2015 , 6 , 7 ) ;
cout << date2- > * pmer << endl;
}
4.1.4成员变量指针的本质
成员变量指针就是记录在对象中的地址偏移量
如上例,如果指针指向month,则偏移量为4
如果指向day,则偏移量为8
如果指向year,则偏移量为0
偏移量即pmer
4.2成员函数指针
4.2.1概念
指向成员函数的指针
4.2.2语法
struct Date{
int year;
int month;
int day;
int getYear(){
return year;
}
int getMonth(){
return month;
}
};
int (Date::*pgetm)();//声明
pgetm = &Date::getMonth;//赋值
/*解引用*/
Date date;
(date.*pgetm)();
Date *date2 = new Date();
(date->*pgetm)();
4.2.3成员函数指针本质
成员函数指针就是函数的绝对地址。没有偏移量这一说。
4.2.4程序举例
#include <iostream>
using namespace std;
struct Date{
int year;
int month;
int day;
Date ( int year= 2014 , int month= 6 , int day= 7 ) : year ( year) ,
month ( month) , day ( day) {
}
int getYear ( ) {
return year;
}
int getMonth ( ) {
return month;
}
} ;
int main ( ) {
Date date;
int ( Date:: * pmfun) ( ) ;
pmfun = & Date:: getMonth;
cout << ( date. * pmfun) ( ) << endl;
}