此博文仅作为C++考研专业课的复习内容。
在对象被创建的时候将自动调用。
形参是本类对象的引用。其作用是使用一个已经存在的对象,去初始化一个同类的新对象。
复制构造函数在以下三种情况会被调用。
当用类的一个对象去初始化该类的另一个对象。
Point a(1,2);
//两种写法都会调用复制构造函数,只是写法上不同。
Point b(a);//用对象a初始化b
Point c = a;////用对象a初始化b
如果函数的形参是类的对象,调用函数时,进行形参和实参结合时。
void foo(Point p){
cout<<p.getX()<<endl;
}
int main(){
Point a(1,2);
foo(a);
return 0;
}
如果函数的返回值是类的对象,函数执行完成返回调用者时。
Point foo(){
Point a(1,2);
return a ;
}
int main(){
Point b;
b= foo();
return 0;
}
注:a离开函数foo()时,a对象会消亡,此时会调用复制构造函数创建一个无名的临时对象存在于表达式b= foo()中。
析构函数是用来完成对象被删除前的一些清理工作,是在对象的生存期即将结束的时候被自动调用的。
析构函数的调用执行顺序与构造函数刚好相反。
类的拷贝构造函数编写。需要为内嵌成员对象的复制构造函数传递参数。
class Point{
public:
Point(Point& p);
};
class Line{
private:
Point p1,p2;
public:
Line(Point& p1,Point& p2);
};
Line::Line(Point& xp1,Point& xp2):p1(xp1),p2(xp2){
//to-do something
}
class B; //前向引用申明
class A{
public:
void foo(B b);
};
class B{
public:
void bar(A a);
};
当类发生循环依赖时,需要使用前向引用申明。但是即便是存在前向引用申明,但是无法直接定义类的对象。
static修饰。类属性是描述类的所有对象共同特征的数据项,对任何实例,他的属性值是相同的。
class Point{
public:
Point(){
count++;
}
void show_count(){
cout<<count<<endl;
}
private:
static int count;
};
int Point::count = 0;
静态数据成员单独在类外初始化,需要专门为他们分配空间。
静态成员函数可以直接访问该类的静态数据和函数成员。而访问非静态成员必须通过对象名。
class A{
public:
static void foo(A a);
private:
int x;
};
void A::foo(A a){
cout<<x; //对x的引用时错误的。
cout<<a.x; //正确。
}
友元关系提供了不同类或对象的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制。
友元的特点
友元函数是在类中用关键字friend修饰的非成员函数。可以是普通函数,也可以是其他类的成员函数。类的友元函数可以通过对象名访问类的私有和保护成员。
class Point{
Point(int x,int y);
int getX();
int getY();
friend float dist (Point &p1,Point &p2);
private:
int x,y;
};
float dist(Point &p1,Point &p2){
double x = p1.x - p2.x;
double y = p1.y - p2.y;
return static_cast<float>(sqrt(x * x + y * y));
}
int main(){
Point p1(1,1),p2(4,5);
cout<<dist(p1,p2);
return 0;
}
同友元函数一样,一个类也可以将另一个类声明为友元类。若A类为B类的友元类,则A类的所有成员都是B类的友元函数,都可以访问B类的私有和保护成员
class A{
public:
int getX();
friend class B; //B是A的友元类
private:
int x;
};
class B{
public:
void set(int i);
private:
A a;
};
void B::set(int i){
a.x = i; //由于B是A的友元类,所以在B的成员函数中可以访问A类对象的私有成员。
};
数据成员值在对象的整个生存期间内不改变。常对象必须进行初始化,而且不能被更新。
const A a(3,4);
类型说明符 函数名 (参数列表) const
eg:void foo() const;
无论是否通过常对象调用常成员函数,在函数调用期间,目的对象都被视为常对象,因此常成员函数不能更新目的对象的数据成员,也不能针对目的对象调用其非const修饰的函数。
class A {
public :
void foo() const{
cout<<"foo const"<<endl;
this->bar();//error C2662: “A::bar”: 不能将“this”指针从“const A”转换为“A &
this->x = 1;//error C3490: 由于正在通过常量对象访问“x”,因此无法对其进行修改
}
void bar(){
cout<<"bar"<<endl;
}
private :
int x;
};
const可以区分函数的重载。例如申明如下函数。
此时常对象会调用第二个,非常对象就近调用第一个。
void print();
void print() const;
常数据成员
常数据成员只能通过构造函数的初始化列表来指定具体值。
class A {
public :
A(int i):a(i){
//a = i; //error
}
private :
const int a;
static const int b;
//static const int b = 10; //正确 int或enum的静态常量可在类中直接指定值。
};
const int A::b = 10;