C++学习(类和对象)
10.2 构造函数
10.2.1 构造函数
构造函数就是建立一个对象,完成对其的初始化工作,赋值操作就在初始化中完成。
class Cperson
{
public:
Cperson();
int index;
int age;
double salary;
Cperson()
{
m_index = 100;
age = 30;
salary = 100;
}
};
int main()
{
Cperson p1;
}
Cperson即为构造函数
10.2.2 复制构造函数
复制构造函数就是用一个已经初始化的对象生成一个一模一样的对象。
class Cperson
{
public:
Cperson();
int index;
int age;
double salary;
Cperson(int iindex,int iage,double isalary)
{
index = iindex;
age = iage;
salary = isalary;
}
Cperson(Cperson ©Person)
{
index = copyPerson.index;
age = copyPerson.age;
salary = copyPerson.salary;
}
};
int main()
{
Cperson p1(20,30,100);
Cperson p2(p1);
}
10.3 析构函数
10.3.1 析构函数
构造函是用来对象创建时,给对象中的一些数据成员赋值,主要目的是初始化对象,而析构函数的功能就是释放对象。
class Cperson
{
public:
Cperson();
~Cperson();
char *message;
};
Cperson::Cperson()
{
message = new char [2048];
strcpy(message,"Hello World!");
}
Cperson::~Cperson()
{
delete[] message;
}
int main()
{
Cperson p1;
}
自动变量的作用域是某个模块,当此模块被激活时,自动变量调用析构函数,当退出此模块时,会调用析构函数。
10.4 类成员
10.4.1 访问类成员
3种类成员为:
public
属性的成员对外可见,对内可见。privite
属性的成员对外不可见,对内可见。protected
属性的成员对外不可见,对内可见,且派生类是可见的。
类定义没有加关键字的话,默认状态类成员都在 private
区域。
10.4.2 内联成员函数
内联函数可以理解成一个安全的宏定义,他就是一个真正的函数,只是不用压栈出栈,速度快,而且比宏定义安全,所以利用 短且频率 比较高的函数可以写成内联函数 inline
。 内联函数在编译时,会将此内联函数代码直接编译到调用函数之处。减少了一次函数调用时的跳转、数据压栈等操作。所以相比调用行数,内联函数的执行效率要相对高点。不过也正因为如此,所以最终生成的程序文件要稍微大点。
1.内联函数可减少cpu的系统开销,并且提高整体程序的速度,但当内联函数很大时,会有相反的作用,因此一般比较小的函数才使用内联函数。
2.有两种内联函数的声明方法,一种是在函数前使用 inline
关键字;另一种是在类的内部定义函数的代码,这样的函数将自动转换为内联函数,而且没必要将 inline
放在函数前面。
class Cperson
{
public:
int age;
Setage()
{
age = 10;
}
};
Setage()
默认为内联函数
class Cperson
{
public:
int age;
void Setage();
};
inline void Cprson::Setage()
{
age = 10;
}
10.4.3 静态类成员
class CBook
{
public:
static unsigned int m_Price;
};
unsigned int CBook::m_Prince = 10;
1.在定义静态数据成员时,通常需要在类外部对静态数据成员初始化。
2.对于静态成员来说,不仅可以通过对象访问,还可以直接使用类名访问。
3.在一个类中,静态成员是被所有的类对象共享的,这就意味着无论定义多少个类对象,类的静态数据成员只有一份,同时,如果某一个对象修改了静态数据成员,其他对象的静态数据成员也将改变。
10.4.4 隐藏的this指针
调用共享的成员函数通过this指针找到自己的数据成员
class Cperson
{
int age;
void Showage()
{
cout << age << endl;
cout << this->age <<endl //两者等效
}
};
10.4.5 嵌套类
C++允许在一个类中定义另一个类,这被称为嵌套类。
class CList
{
public:
class CNode //在CList中定义一个CNode类
{
friend class CList; //CList是自己的友元可以访问自己的私有成员
private:
int m_Tag;
public:
int m_id;
};
public:
CNode m_Node;
void Init()
{
m_Node.m_Tag = 10; //m_Tag为私有区域,CList为Node的友元类,因此CList可以访问Node的私有成员。
m_Node.m_id = 123;
}
};
int main()
{
CList List;
CList::CNode node; //CNode类的定义
List.Init();
cout << List.m_Node.m_id;
}
对于main函数来说,嵌套类CNode是不可以见的,但是可以通过使用外围的类域作为限定符来定义Cnode对象。
10.4.6 局部类
类的定义放在函数中,这样的类被称为局部类。
void LocalClass()
{
class CBook
{
private:
int m_Pages;
public:
void SetPages(int page)
{
m_Pages = page;
}
int GetPages()
{
return m_Pages;
}
};
CBook book;
book.SetPages(300);
cout << book.GetPages() << endl;
}
对于局部类CBook,在函数之外是不能被访问的,因为局部类被封装在了函数的局部作用域。
10.5 友元
10.5.1 友元概述
有时候,类会允许一些特殊的函数直接读写其私有数据成员。使用friend关键字可以让特定的函数或者别的类的所有成员对私有数据成员进行读写。
class CRectangle
{
public:
CRectangle()
{
m_Height = 0;
m_Width = 0;
}
void SetRectangle(int Height, int Width)
{
m_Height = Height;
m_Width = Width;
}
protected:
int m_Height;
int m_Width;
friend int ComputerRectArea(CRectangle& myRect);
};
int ComputerRectArea(CRectangle& myRect)
{
return myRect.m_Height * myRect.m_Width;
}
int main()
{
CRectangle rectangle;
rectangle.SetRectangle(100, 10);
cout << ComputerRectArea(rectangle) << endl;
return 0;
}
ComputerRectArea
被定义为友元函数,可以直接访问私有数据。
10.5.2 友元类
对于类的私有方法,只有在该类中允许访问,其他的类不允许访问。如果两个类的耦合度比较紧密,可以在当前类中将另一个类作为自己的友元类,这样在另一个类中就可以访问当前类的私有成员了。
class CItem
{
private:
int id;
public:
friend class CList;
};
class CList
{
public:
CItem item;
void Outputid()
{
item.id = 10;
cout << item.id << endl;
}
};
CList类作为CItem类的友元类,在CList类中可以直接访问CItem的私有成员。
10.5.3 友元函数
友元函数不是当前类的成员函数,它既可以是一个不属于任何类的一般函数,也可以是另外一个类的函数。将一个函数声明为一个类的友元函数后,它不但可以通过对象名访问类的公有成员,而且可以通过对象名访问类的私有成员和保护成员。
class Date
{
private:
int day;
public:
friend void SetDay(Date& date, int d);
};
void SetDay(Date& date, int d)
{
date.day = d;
cout << date.day << endl;
}
int main()
{
Date date;
SetDay(date, 20);
return 0;
}
当友元函数在另外一个类中时,友元函数的定义不能在类内。
class Date; //需要提前声明
class Time
{
public:
void Display(Date& date);
void Setdate(Date& date, int d);
};
class Date
{
private:
int day;
public:
friend void Time::Display(Date& date);
friend void Time::Setdate(Date& date,int d);
};
void Time::Display(Date& date)
{
cout << date.day << endl;
}
void Time::Setdate(Date& date, int d)
{
date.day = d;
}
int main()
{
Time time;
Date date;
time.Setdate(date,200);
time.Display(date);
return 0;
}
10.6 命名空间
10.6.1 使用命名空间
在一个应用程序中会存在同名的全局变量,这样会导致程序的链接错误,使用命名空间可以消除命名冲突。
namespace Myname1
{
int a = 10;
};
namespace Myname2
{
int a = 20;
};
int main()
{
cout << Myname1::a << endl;
cout << Myname2::a << endl;
return 0;
}
总而言之,命名空间就是一个命名的范围区域,程序员在这个特定的范围内创建的所有标识符都是唯一的。
10.6.2 在多个文件中定义命名空间
在定义命名空间时,通常在头文件中声明命名空间中的函数,在源文件中定义命名空间的函数,将程序的声明与实现分开。
在头文件中声明命名空间函数
namespace Output
{
void Demo();
}
在源文件中定义函数
void Output::Demo()
{
cout << "Hello World!" << endl;
}
在主函数中调用函数
void Output::Demo()
{
Output::Demo();
}
10.6.3 定义嵌套的命名空间
命名空间可以定义在其他的命名空间中。
namespace Output
{
void Show()
{
cout << "Hello World" << endl;
}
namespace Myname
{
void Demo()
{
cout << "何永旗" << endl;
}
}
}
int main()
{
Output::Show();
Output::Myname::Demo();
return 0;
}