一:当类的实例化使用 perosn p() 会出现的情况:
当构造函数有多个时:
class person
{
public:
person()
{
cout << "构造函数11111" << endl;
}
person(int a,int b)
{
cout << "构造函数22222" << endl;
}
int _a;
double _b;
};
int main() {
person p;
person p1(10,10);
person p2();
return 0;
}
person p2();没有执行构造函数,但也没有报错
但在该行后面加一段代码:
p2._a=10;
p1=p2;
在这里可以看出,p2并不是一个对象 而是一个对象函数
当没有构造函数时:也是如此
class person
{
public:
int _a;
double _b;
};
int main() {
person p;
person p2();
p2._a=10 //报错
return 0;
}
总结:person p2(); 仅仅代表一个生成的是 person 对象的函数。并不能生成一个对象
二:创建对象的方式
一个无参构造函数
以下这几种都能创建:
class person
{
public:
person()
{
cout << "构造函数" << endl;
}
int _a;
double _b;
};
int main()
{
person p1;
person p2{};
person *pp1 = new person;
person *pp2 = new person();
person *pp3 = new person{};
cout << p1._a<<endl;
cout << p2._a << endl;
cout << pp1->_a << endl;
cout << pp2->_a<<endl;
cout << pp3->_a << endl;
return 0;
}
当类中没有构造函数时:
class person
{
public:
int _a;
double _b;
};
int main()
{
person p1;
person p2{};
person *pp1 = new person;
person *pp2 = new person();
person *pp3 = new person{};
cout << p1._a<<endl; //报错,使用了未初始化的局部变量
cout << p1._b<<endl; //报错,使用了未初始化的局部变量
cout << p2._a << endl; //结果为 0
cout << p2._b << endl; //结果为 0
cout << pp1->_a << endl; //结果为-842150451
cout << pp1->_b << endl; //结果为-6.27744e+66
cout << pp2->_a<<endl; //结果为 0
cout << pp2->_b<<endl; //结果为 0
cout << pp3->_a << endl; //结果为 0
cout << pp3->_b << endl; //结果为 0
return 0;
}
当没有给出构造函数时:
- 实例化后面带有()或{ }会给与默认值 为 0
- 当实例化指针时,不带括号的初始化为最小值
- 当实例化一个普通对象时,生成的是一个为初始化的值,(是一个变值)无法输出
构造函数的权限:
- public 类型 可以创建多个对象
- protected 类型和private 类型
public 类型的用法: 可以在栈中生成对象
class person
{
public:
person(int a,double b):_a(a),_b(b){}
int _a;
double _b;
};
int main()
{
person p(10, 20);//生成局部对象,放在栈中
}
protected 类型的用法:只能构造该类的子类
class person
{
public:
int _a;
double _b;
protected:
person(int a, double b) :_a(a), _b(b) {}
~person(){}
};
class son :public person
{
public:
son(int a,double b,int c):person(a,b),_c(c){}//初始化父类的数据
int _c;
};
int main()
{
son p(10, 20, 30);
person p(10,20);//报错,类对象无法调用类中的保护类型数据
}
private 类型的用法:生成单例模式
class person
{
private:
int _a;
double _b;
person(int a, double b) :_a(a), _b(b) {}
~person(){}
public:
static person& p1()
{
static person p(10, 20);
return p;
}
};
int main()
{
person::p1();//通过static生成一个对象
}
析构函数的权限:
- public
- protected
- private
编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性,其实不光是析构函数,只要是非静态的函数,编译器都会进行检查。如果类的析构函数是私有的,则编译器不会在栈空间上为类对象分配内存。 因此, 将析构函数设为私有,类对象就无法建立在栈(静态)上了,只能在堆上(动态new)分配类对象
三:父类和子类之间的赋值关系
普通对象之间的赋值:
- 子类对象可以赋值给父类对象
- 父类对象不可以赋值给子类对象(父类中可能不包含子类中的成员)
- 普通的对象采用的是拷贝
class person
{
public:
person(int a,int b):_a(a),_b(b){}
int _a;
int _b;
};
class son :public person
{
public:
son(int a,int b,int c):person(a,b),_c(c){}
int _c;
};
int main() {
person p(1, 2);
son s(10,20,30);
p = s;//可以,子类对象会把父类的那一部分赋值给父类对象
cout << p._a << " " << p._b << endl;
//s = p;//报错
return 0;
}
指针对象之间的赋值:(引用之间的赋值和指针相同 )
- 子类对象可以赋值给父类对象
- 父类对象不可以赋值给子类对象(父类中可能不包含子类中的成员)
- 指针对象采用的是改变指向
class person
{
public:
person(int a,int b):_a(a),_b(b){}
int _a;
int _b;
};
class son :public person
{
public:
son(int a,int b,int c):person(a,b),_c(c){}
int _c;
};
int main() {
person *p = new person(1, 2);
son *s = new son(10, 20, 30);
p = s;
cout << p->_a << " " << p->_b << endl;
//s=p//报错
return 0;
}
int main() {
person *p = new person(1, 2);
son *s = new son(10, 20, 30);
p = s;
cout << p << endl;//取p的地址
cout << s << endl;//取s的地址
return 0;
}
int main() {
son s(10, 20, 30);
person &p = s;
cout << &p << endl;//取p的地址
cout << &s << endl;//取s的地址
return 0;
}
四:重载,覆盖,隐藏
以下为成员函数
重载:
- 在同一个类中
- 函数名相同
- 函数参数不同
- virtual可有可无
覆盖:
- 在不同的类中(父类和子类)
- 必须为虚函数(带有virtual)
- 函数名相同
- 函数参数相同
隐藏:
- 当继承时,子类和父类中有同名函数且参数不同,父类中的同名函数会隐藏(不为virtual)
- 当继承时,子类和父类有同名函数且参数相同时,(不为virtual时)父类同名函数会被隐藏