1,常量数据成员
加上const 的数据成员,加上之后只能在声明和初始化队列中进行初始化,初始化之后不能进行赋值操作
2,引用数据数据成员
用引用方式创建的数据成员
引用数据成员需要在初始化列表中进行初始化
需要绑定一个已经存在的,在引用成员的生命周期内始终有效的变量(对象
3,对象成员
一个类的对象是其他类的数据成员
coution:
初始化列表写对象,不写类名,不能在声明对象成员时直接用有参构造创建
如果在初始化列表中没有显示的初始化对象成员,编译器回自动调用对象成员的默认无参构造或者所有参数都有默认值的有参
堆空间资源回收顺序(类的对象-->对象成员)
4,静态数据成员
加上static修饰的数据成员
存储在全局/静态区,不占据对象的存储空间,静态数据成员被整个类的所有对象共享
规则:
4.1 private 的静态数据成员无法在类之外直接访问
4.2 初始化必须放在类外(一般紧接类定义
4.3 初始化时不能在前面+static,要加类名+作用域限定符
4.4 多条初始化顺序和声明顺序一致
4.5 对象访问 & 类名::访问
#include
using std::cout;
using std::endl;
class Point{
public:
Point()
//只能用 这种 严格意义的初始化
/* :_ix(0),_iy(0) */
{cout<<"Point()"<
#include
using std::cout;
using std::endl;
int gNum=100;
//只能绑定一个已经存在,在引用期间成员的生命周期内
//始终有效的变量(对象
class Point{
public:
Point()
:_ix(0),_iy(0)
,_ref(_ix)
{cout<<"Point()"<
#include
using std::cout;
using std::endl;
class Point{
public:
Point()
:_ix(0),_iy(0)
{cout<<"Point()"<";
_pt2.print();
cout<
#include
#include
using std::cout;
using std::endl;
class Computer{
public:
/* void init(const char* brand,int price){ */
/* strcpy(_brand,brand); */
/* _price=price; */
/* } */
void printBrandPrice(){
cout<<_brand<<"\t";
cout<<_price<
#include
#include
using std::cout;
using std::endl;
class Computer{
public:
void init(int price)/*const*/{
_price=price;
}
void printBrandPrice()const{
cout<<_brand<<"\t";
cout<<_price<<"\tconst_print"<
#include
#include
using std::cout;
using std::endl;
class Computer{
public:
void init(int price)/*const*/{
_price=price;
}
void printBrandPrice(const Computer & c)const{
/* for(int i=0;i
#include
using std::cout;
using std::endl;
class Point{
public:
Point()
:_ix(0),_iy(0)
{cout<<"Point()"<print();
(*p1).print();
delete p1;
//()确保进行了初始化,初始化为相应类信息的默认值
int *p=new int();
cout<<*p<print();
delete p2;
//------------------------------//
cout<print();
cout<
#include
#include
using std::cout;
using std::endl;
class Student
{
public:
Student(int id, const char * name)
: _id(id)
, _name(new char[strlen(name) + 1]())
{
strcpy(_name, name);
cout << "Student()" << endl;
}
~Student(){
if(_name){
delete [] _name;
_name = nullptr;
}
}
//------------------------------//
void operator delete(void * pointer){
cout<<"operator delete"<print();
delete s;
}
int main(void)
{
test();
return 0;
}
#include
#include
using std::cout;
using std::endl;
class Student
{
public:
Student(int id, const char * name)
: _id(id)
, _name(new char[strlen(name) + 1]())
{
strcpy(_name, name);
cout << "Student()" << endl;
}
~Student(){
if(_name){
delete [] _name;
_name = nullptr;
}
}
//------------------------------//
void operator delete(void * pointer){
cout<<"operator delete"<print();
s->destroy();
/* delete s; */
}
int main(void)
{
test();
return 0;
}
#include
#include
using std::cout;
using std::endl;
class Student
{
public:
Student(int id, const char * name)
: _id(id)
, _name(new char[strlen(name) + 1]())
{
strcpy(_name, name);
cout << "Student()" << endl;
}
~Student(){
if(_name){
delete [] _name;
_name = nullptr;
}
}
void print() const{
cout << "id:" << _id << "\t"<< "name:" << _name << endl;
}
private:
//------------------------------//
void operator delete(void * pointer){
cout<<"operator delete"<
#include
using std::cout;
using std::endl;
class Point{
public:
Point()
:_ix(0),_iy(0)
{cout<<"Point()"<
#include
using std::cout;
using std::endl;
//堆上创建单例对象
class Point{
public:
static Point * getInstance(){
if(_pInstance==nullptr){
_pInstance=new Point(1,2);
}
return _pInstance;
}
static void destroy(){
if(_pInstance){
delete _pInstance;
_pInstance=nullptr;
}
cout<<"<<print();
Point::getInstance()->init(21,13);
Point::getInstance()->print();
Point::getInstance()->init(23,231);
Point::getInstance()->print();
Point::destroy();
Point::destroy();
Point::destroy();
//多次执行也不会有double free的问题
Point::getInstance()->print();
Point::destroy();
}
int main(void)
{
test();
return 0;
}
1,static成员函数
0.1 静态成员函数不依赖于某一对象
0.2 静态成员函数可以通过对象调用,但更加常见的方式是通过类名加上作用域限定符调用
0.3 静态成员函数没有this指针
0.4 静态成员函数中无法直接使用成员名访问非静态的成员,只能访问静态数据成员或调用静态成员(因为没有this指针),但是非静态的成员函数可以访问静态成员
0.5 构造/析构/赋值运算符/拷贝构造比较特殊,可以在静态成员函数中调用(这四个函数不能设置为静态成员函数,他们会访问所有的成员对象,但是静态成员函数没有this指针)
2,const成员函数
0.1 cosnt 成员函数中,不能修改对象的数据成员
0.2 当编译器发现该函数是const成员函数时,会自动将this指针设置为双重const限定的指针
const 对象与const 成员函数的规则:
当类中有const成员函数和非const成员函数重载时,const对象会调用const成员函数,非const对象会调用非const成员函数
当类中只有一个const成员函数时,无论const对象还是非const对象都可以调用这个版本
当类中只有一个非const成员函数时,const对象就不能调用非const版本
总结:如果一个成员函数中确定不会修改数据成员,就把它定义为const成员函数
class Sample
{
public:
Sample();
void Display();
private:
int i;
static int k;
};
Sample::Sample()
{
i=0;
k++;
}
void Sample::Display()
{
cout << "i=" << i << ",k=" << k << endl;
}
int Sample::k=0;
int main( )
{
Sample a, b;
a.Display();
b.Display();
return 0;
}
i=0,k=1(2)坏
i=0,k=2
#include
using std::cout;
using std::endl;
int i = 1;
class Test
{
public:
Test()
:_first(i++) //1 2
,_second(i++)//2 3
,_third(i++)//3 4
,_fourth(_third)//3
{
_third = i;//4 _foruth=4
}
void print()
{
cout << "result : " << _first + _second + _third + _fourth << endl;
//1 2 4 4 =11
}
private:
int _first;
int _second;
int _third;
int &_fourth;
};
int main()
{
Test test;
test.print();
return 0;
}
#include
#include
using std::cout;
using std::endl;
class Point
{
public:
Point(int xx = 0, int yy = 0)
{
X = xx;
Y = yy;
cout << "point构造函数被调用" << endl;
}
Point(Point &p);
int GetX()
{
return X;
}
int GetY()
{
return Y;
}
private:
int X,Y;
};
Point::Point(Point &p)
{
X = p.X;
Y = p.Y;
cout << "X = " << X << " Y=" << Y << "Point拷贝构造函数被调用" << endl;
}
class Distance
{
public:
Distance(Point xp1, Point xp2);
double GetDis()
{
return dist;
}
private:
Point p1,p2;
double dist;
};
//拷贝一次
Distance::Distance(Point xp1, Point xp2)
: p1(xp1)//拷贝一次
, p2(xp2)
{
cout << "Distance构造函数被调用" << endl;
double x = double(p1.GetX() - p2.GetX());
double y = double(p1.GetY() - p2.GetY());
dist = sqrt(x * x + y * y);
}
int main()
{
//point构造函数被调用
//point构造函数被调用
Point myp1(1,1), myp2(4,5);
//X=1,Y=1,Point拷贝构造函数被调用
//X=4,Y=5,Point拷贝构造函数被调用
//X=1,Y=1,Point拷贝构造函数被调用
//X=4,Y=5,Point拷贝构造函数被调用
Distance myd(myp1, myp2);
//Distance构造函数被调用
cout << "The distance is:" ;
//The distance is:dist
cout << myd.GetDis() << endl;
return 0;
}
point构造函数被调用
point构造函数被调用
X = 4 Y=5Point拷贝构造函数被调用
X = 1 Y=1Point拷贝构造函数被调用
X = 1 Y=1Point拷贝构造函数被调用
X = 4 Y=5Point拷贝构造函数被调用
Distance构造函数被调用
The distance is:5
#include
using std::cout;
using std::endl;
class MyClass
{
public:
MyClass(int i = 0)
{
cout << i;
}
MyClass(const MyClass &x)
{
cout << 2;
}
MyClass &operator=(const MyClass &x)
{
cout << 3;
return *this;
}
~MyClass()
{
cout << 4;
}
};
int main()
{
MyClass obj1(1), obj2(2);
//12
MyClass obj3 = obj1;//==Myclass obj3(obj1);
//32444
return 0;
}
-fno-elide-constructors
编译时消除优化的影响#include
using std::cout;
using std::endl;
class B
{
public:
B()
{
cout << "B()" << endl;
}
~B()
{
cout << "~B()" << endl;
}
B(const B &rhs)
{
cout << "B(const B&)" << endl;
}
B &operator=(const B &rhs)
{
cout << "B &operator=(const B &s)" << endl;
return *this;
}
};
B func(const B &rhs)
//cp 不是喵是赋值
{
cout << "B func(const B &)" << endl;
return rhs;
}
int main(int argc, char **argv)
{
B b1,b2;
b2=func(b1);//10#
//B func(const B &)
//B(const B&)
//B &operator=(const B &s)
return 0;
}
B func(const B &)
B(const B&)
B &operator=(const B &s)
1,对于自定义类型而言
使用new表达式的三个步骤:
1,调用operator new标准库函数申请未类型化的空间
2,在该空间上调用该类型的构造函数初始化对象
3,返回指向该对象的相应类型的指针
使用delete表达式···
1,调用析构函数,回收数据成员申请的资源(堆空间)
2,调用operator delete库函数回收本对象所在的空间
对于内置类型而言,则没有以上构造函数和析构函数执行的步骤
heap_single.cc
#include
#include
using std::cout;
using std::endl;
class Computer{
public:
static Computer * get(){
if(!_pp){
_pp=new Computer("xixi",520);
}
return _pp;
}
/* void* operator new(size_t sz){ */
/* void * ret=malloc(sz); */
/* return ret; */
/* } */
/* void operator delete(void * p){ */
/* free(p); */
/* } */
static void destory(){
if(_pp){
delete _pp;
_pp=nullptr;
}
cout<<"<<<< destory"<printBrandPrice();
Computer::get()->init("jiajia",7758258);
Computer::get()->printBrandPrice();
Computer::get()->init("yueyue",51930);
Computer::get()->printBrandPrice();
Computer::destory();
Computer::destory();
Computer::destory();
}
void test01(){
}
int main(void)
{
test();
test01();
return 0;
}