class A {
int Fun();
}
int A::Fun()
{
...
}
private
and public
class A {
public:
...
private:
...
public:
...
}
没有关键字的视为private
class A {
int a; // private
int Fun(); //private
public:
int b; // public
};
private
成员只能在成员函数内部访问,public
成员可以在任何地方访问
对象的公共成员
#include
#include
class CEmployee {
private:
char szName[30];
int getSalary();
public:
int salary;
void setName(const char * name);
void getName(char * name);
void averageSalary(CEmployee e1, CEmployee e2);
};
void CEmployee::setName(const char * name)
{
strcpy(szName, name); //直接使用私有成员szName,合法
}
void CEmployee::getName(char * name)
{
strcpy(name, szName);//直接使用私有成员szName,合法
}
int CEmployee::getSalary()
{
return salary;
}
int main()
{
CEmployee A;
char name[30];
A.setName("Tom"); // 合法
A.getSalary(); // 非法,直接在其他地带调用私有函数
strcpy(name, A.szName); // 非法,直接使用私有变量
return 0;
}
成员函数也可以重载和参数缺省
但是要避免二义性错误, 如
class A {
void Fun();
void Fun(int a = 0);
}
int main()
{
Fun();// ambiguous
}
void
)也不行A::A(A)
式的构造函数private
构造函数private
构造函数不能用来直接初始化对象
#include
class Complex {
double real, imag; // private
public:
Complex(double real, double imag);
Complex(double i);
Complex(Complex, Complex);
};
Complex::Complex(double r, double i)
{
real = r;
imag = i;
}
Complex::Complex(double i)
{
real = i;
imag = 0;
}
Complex::Complex(Complex c1, Complex c2)
{
real = c1.real + c2.real;
imag = c1.imag + c2.imag; // 均合法,使用同类对象私有变量
}
int main()
{
Complex a; // 非法,无参缺省构造函数已停用
Complex c1(4), c2(2, 1); // 自动转化为 double
Complex c(c1, c2);
Complex * p = new Complex(1);
return 0;
}
#include
class Test {
public:
int x;
Test()
{
std::cout << "Constructor 1 Called." << std::endl;
}
Test(int i)
{
x = i;
std::cout << "Constructor 2 Called." << std::endl;
}
Test(int a, int b)
{
x = a + b;
std::cout << "Constructor 3 Called." << std::endl;
}
};
int main()
{
Test A[2] = {2}; // A[1]只有一个空元素也要调用constructor
std::cout << "Step 1" << std::endl;
Test B[2] = {Test(2, 1), 5};
std::cout << "Step 2" << std::endl;
Test * P = new Test[2]{1, Test(2,1)}; // 这种初始化方式C++11才有,warning: 额外的初始化,new feature
std::cout << "Step 3" << std::endl;
delete []P;
Test * PA[3] = {new Test(1), new Test(1,2), NULL}; // PA[2]只有一个指针不调用constructor
delete PA[1];
delete PA[0];
std::cout << "Step 4" << std::endl;
return 0;
}
输出
Constructor 2 Called.
Constructor 1 Called.
Step 1
Constructor 3 Called.
Constructor 2 Called.
Step 2
Constructor 2 Called.
Constructor 3 Called.
Step 3
Constructor 2 Called.
Constructor 3 Called.
Step 4
const
或非const
,一般使用const
)#include
class A {
public:
int v;
A(int i)
{
v = i;
}
};
int main()
{
A c1(5);
A c2(c1); // 缺省的复制构造函数被调用
std::cout << c1.v << std::endl;
std::cout << c2.v << std::endl;
return 0;
}
输出
5
5
用一个对象初始化另一个同类的对象
#include
class A {
public:
int v;
A(int i)
{
v = i;
}
A(A & a)
{
v = a.v;
std::cout << "Copy constructor called." << std::endl;
}
};
int main()
{
A c1(5);
A c2(c1); // 初始化,复制构造函数被调用
A c3 = c2; // 同样是初始化语句,而非赋值语句,复制构造函数被调用
c1 = c2; // 赋值语句,不调用复制构造函数
return 0;
}
Output
Copy constructor called.
Copy constructor called.
函数参数为类的对象,形参会被复制构造函数初始化
#include
class A {
public:
int v;
A(int i)
{
v = i;
}
A(A & a)
{
v = a.v;
std::cout << "Copy constructor called." << std::endl;
}
};
void Fun(A a)
{
std::cout << a.v << std::endl;
}
int main()
{
A c1(5);
Fun(c1); // 复制构造函数被调用形成形参
return 0;
}
Output
Copy constructor called.
5
函数返回值为类的对象,返回时,复制构造函数初始化返回值
#include
class A {
public:
int v;
A(int i)
{
v = i;
}
A(A & a)
{
v = a.v;
std::cout << "Copy constructor called." << std::endl;
}
};
A Fun(A a)
{
std::cout << a.v << std::endl;
return a;
}
int main()
{
A c1(5);
std::cout << Fun(c1).v << std::endl; // 复制构造函数被调用形成形参,再被调用形成返回值
return 0;
}
Output
Copy constructor called.
5
Copy constructor called.
5
& A
类型),即可称为类型转换构造函数#include
class Complex {
public:
double real, imag;
Complex(int i) // convert int into Complex
{
std::cout << "IntConstructor Called." << std::endl;
real = i;
imag = 0;
}
Complex(double r, double i)
{
real = r;
imag = i;
}
};
int main()
{
Complex aa(4,5);
Complex a(4); // 类型转换构造函数被调用,用于初始化a,不产生临时变量
Complex aaa = 4; // 同样用于初始化,不产生临时变量
aaa = 9; // 类型转换构造函数被调用,先生成Complex(9)初始化的临时变量,再赋给aaa
return 0;
}
Output:
IntConstructor Called.
IntConstructor Called.
IntConstructor Called.
~
符号对象数组消亡时,每个对象的析构函数都会被调用
指针所指的动态分配的对象,不delete就不会消亡,也不调用析构函数
对象在以返回值返回时,先调用赋值构造函数生成临时变量,而后消亡调用析构函数,随后临时变量也会消亡,也调用析构函数。
#include
class A {
public:
~A()
{
std::cout << "Destructor Called." << std::endl;
}
};
int main()
{
A Test[2]; // 两个对象,消亡时调用两次析构函数
A * P = new A[3]; //三个对象, 不delete就不调用析构函数
return 0;
}
Output:
Destructor Called.
Destructor Called.
#include
class A {
public:
int x;
A(int i)
{
x = i;
}
A(A & a)
{
x = a.x;
std::cout << "Copy called" << std::endl;
}
~A()
{
std::cout << x << "Destructor Called" << std::endl;
}
};
A Fun()
{
A b(4);
return b;
}
A a(5);
int main()
{
a = Fun(); //
std::cout << "main ends" << std::endl;
return 0;
}
Output:
Copy called
4Destructor Called //b
4Destructor Called //临时变量
main ends4Destructor Called //a
在许多编译器中,函数的类的对象类型的返回值不会调用复制构造函数生成临时变量,也不会调用析构函数,比如VS在Debug 和 Release 两种模式下,表现是不一样的。