C++ 是面向对象的编程语言,那什么是面向对象呢?一切皆对象,而类就是我们说的对象的类型,所以这也是C++的最最重要的内容,我们今天就开始一点一点的学习。
一、类基本的几个函数(构造函数,析构函数,拷贝构造函数)
说明:
1、如果没有写构造函数,那么创建对象时,默认调用无参数构造函数,若声明了构造函数,则创建对象不会调用默认构造函数
2、析构函数在调用delete后会自动调用,在析构函数中做是否的工作
3、C语言中的malloc 与free 并不会调用构造和析构函数,
4、new/delete 是一套 会调用构造函数 与 析构函数 【C++标准规范】
**malloc/free是一套 不调用构造函数 与 析构函数 【C的范畴,虽然不推荐,但是也是可以的】**
5、拷贝构造函数默认是有的,一旦我们自己写了拷贝构造函数就会覆盖默认的拷贝构造函数
6、拷贝构造函数只有在创建对象时赋值才会被调用,如果对象创建好后再去赋值,则会走默认的赋值来完成
7、如果定义的类的成员时对象成员,必须要在构造函数中这样初始化(构造函数后面 :+对象成员(内容))
先来看看我们自定义一个类:
class Student {
public:
//公有域
Student() {
//无参数构造函数,默认构造,可以不写
cout << "无参数构造函数" << endl;
}
//带参数构造函数,
Student(string name, int age) : name(name), age(age) {
cout << "带参数构造函数" << endl;
cout << "带参构造函数:" << "name=" << name << ",age=" << age << endl;
}
//拷贝构造函数
Student(const Student &student) {
cout << "拷贝构造函数" << endl;
this->name = student.name;
this->age = student.age;
cout << "拷贝构造函数:" << "name=" << name << ",age=" << age << endl;
}
//析构函数,用在在对象被delete时,释放资源
~Student() {
cout << "析构函数" << endl;
}
protected:
//半公有域
private:
//私有域
string name;
int age;
};
int main(){
/**
* 4、误区
* 指针的赋值不会执行构造函数,因为他仅仅是指针变量指向的问题,也就是指向同一个地址而已
*/
cout << "误区----演示" << endl;
Student *zhangsan = new Student("张三", 33);
Student *lisi = zhangsan;
cout << endl;
/**
* 3、拷贝构造函数
*/
cout << "拷贝构造函数----演示" << endl;
Student org_Student("leon", 18);
Student copy_Sdu = org_Student;//会调用拷贝构造函数
cout << endl;
/**
* 下面不会走拷贝构造函数,只会调用默认的赋值
*/
Student copy_Sdu2;
copy_Sdu2 = org_Student;
cout << endl;
/**
* 2、带参构造函数
*/
cout << "带参构造函数----演示" << endl;
Student *leon_Student = new Student("leon", 18);
delete leon_Student;
leon_Student = NULL;
cout << endl;
/**
* 1、默认构造函数与析构函数
*/
cout << "默认构造函数与析构函数----演示" << endl;
Student *student = new Student();
delete student;
student = NULL;
return 0;
}
上面的代码注释写的很清楚了,就不啰嗦了,自己拿去允许一下,体会体会就懂了。
二、类的静态成员、方法与友元函数
说明:
1、类的static(成员与函数)通过类名+::来访问,不属于对象
2、类的static 成员不能直接赋值,会报错。例如: static int age = 9;
3、静态的属性必须要初始化,然后再实现(规则)
4、静态方法不能调用非静态方法和成员;非静态函数可以调用静态或非静态的方法和成员;
5、静态成员和方法在.h中声明时需要static,在.cpp文件中不需要,和普通方法一样了;
6、友元函数(好朋友关系,所以可以访问私有成员):在.h中声明时,需要用friend来声明,在.cpp中则不需要friend ,也不需要类名+:: ,只需要函数名,返回,参数即可
7、友元关系不传递(例如:A和B是好朋友,B和C是好朋友,那么A和C就不一定是好朋友)
示例代码:
// 静态demo
class Student {
public:
static int age;
char *sex;
static void show() {
age = 100;
// update(); //静态函数不能调用非静态函数,
// sex="m"; //静态函数不能访问非静态的成员
}
void update() {
int value = age * 10;
show();
}
};
//友元demo
class ImageView {
private:
int width = 100;
int height = 110;
string url = "hello";
friend class Activity;//Activity类是ImageVIew的好友
};
class Activity {
private:
ImageView img;
int index;
public:
void getInfos() {
cout << "通过友元访问对象的私有成员:width= " << img.width << ",height=" << img.height << ",url=" << img.url << endl;
}
// 定义友元函数 (声明,没有实现)
friend void updateInfos(Activity &activity, int width, int height, string url);
};
void updateInfos(Activity &activity, int width, int height, string url) {
// activity->img.width=width;//不传递关系
activity.index = 100;
cout << "友元函数访问私有成员index=" << activity.index << endl;
}
int main() {
Activity activity;
activity.getInfos();
updateInfos(activity, 0, 0, "");
return 0;
}
三、类的继承(多继承、虚继承)
说明:
1、多继承,若多个父类拥有想到的成员或方法,编译时会导致二义性( error: request for member 'show' is ambiguous)
**解决二义性的方法:** **1.1) 重写二义性方法;** **1.2) 通过.来指明父类,再通过:: 来调用二义性的方法 格式:对象.父类名::函数名** **1.3) 虚继承:为多个父类重名的成员和方法提取到一个新的祖父类中(即 虚基类)**
2、继承关系:
默认的的继承关系是private;可以显式指定继承关系,public ,private ,protected
**1) private 继承:子类内部仅能访问父类非私有的成员和方法,子类对象不能访问父类的所有成员和方法;** **2) protected 继承:子类内部仅能访问父类非私有的成员和方法,子类对象不能访问父类的所有成员和方法;** **3) public 继承:子类内部仅能访问父类非私有的成员和方法,子类对象可以访问父类的public成员和方法;**
小结:
**继承后,子类内部只能范文父类的非私有成员和方法,外部之类对象只有在public继承时可以访问父类的public成员和方法,其他都不可以访问**
3、继承关系的构造析构函数的调用顺序
**构造函数:先调用父类,再调用子类;** **析构函数:先调用子类,再调用父类;**
多继承 示例代码:
//多继承
class Base1 {
public:
void show() {
cout << "Base1::show()" << endl;
}
};
class Base2 {
public:
void show() {
cout << "Base2::show()" << endl;
}
};
class MainActivity : public Base1, public Base2 {
public:
/**
* 覆盖父类的方法
*/
void show() {
cout << "mainActivity::show()" << endl;
}
};
int main(){
MainActivity mainActivity;
mainActivity.show();
mainActivity.Base1::show();
return 0;
}
虚继承 示例代码:
//虚继承
class GrandParent {
public:
char *name;
int age;
char *familyName;
};
class Father : virtual public GrandParent {
};
class Mother : virtual public GrandParent {
};
class Child : public Father, public Mother {
};
int main(){
Child child;
child.name = "xiaoming";
cout << "虚继承后,child 的name=" << child.name << endl;
return 0;
}
四、类的多态(虚函数)
说明:
多态(虚函数):程序在允许期间才能确定调用哪个类的函数 ,这就是动态多态的范畴;
1、概念:父类的引用指向子类的对象,同一个方法有不同的实现,重写(动态多态:运行时确定)和 重载(静态多态:编译期确定);
2、java 默认支持多态的,而C++的多态默认是关闭掉了的, 那我们需要需要在父类的函数上加上virtual 关键字即可打开;
3、创建子类实例时,可以用父类对象来接受;
示例代码:
//多态的demo
class BaseActivity {
public:
virtual void onCreate() {
cout << "BaseActivity:onCreate()" << endl;
}
};
class HomeActivity : public BaseActivity {
public:
//重载:静态多态
void onCreate() override {
cout << "MainActivity:onCreate()--override" << endl;
}
};
class PersonActivity : public BaseActivity {
public:
//重写了:动态多态
void onCreate() {
cout << "PersonActivity:onCreate()" << endl;
}
};
void gotoActivity(BaseActivity *baseActivity) {
baseActivity->onCreate();
}
int main(){
BaseActivity * homeActivity = new HomeActivity();
BaseActivity * personActivity = new PersonActivity();
gotoActivity(homeActivity);
gotoActivity(personActivity);
delete homeActivity;
delete personActivity;
return 0;
}
五、抽象类与纯虚函数
说明:
1、C++ 没有抽象类,但是有纯虚函数,就相当于Java的抽象类;
2、纯虚函数是必须要继承的,而虚函数则不是必须继承;
3、纯虚函数和虚函数的区别是:纯虚函数没有实现,直接赋值=0 即可;虚函数是有实现的;
4、如果子类没有实现纯虚函数,那么该子类是无法实例化的(即:子类就是抽象类,编译期就会报错);
5、纯虚函数的格式:virtual void getLayoutID()=0;
6、如果一个类的所有的方法都是纯虚函数,那么这个类就等价于java的接口;
7、有存续函数的类无法实例化,编译期会报错;
示例代码:
//全部是纯虚函数---类似于interface
class BaseBaseActivity{
public:
virtual void onCreate()=0;
virtual int getLayoutID()=0;
};
//有纯虚函数---抽象类
class BaseActivity : public BaseBaseActivity {
public:
virtual void onCreate() {
cout << "BaseActivity:onCreate()" << endl;
}
//纯虚函数,如果加上这句话,子类没有实现该纯虚函数,那么该子类是无法实例化的
virtual int getLayoutID()=0;
};
//
class HomeActivity : public BaseActivity {
public:
//重载:静态多态
void onCreate() override {
cout << "MainActivity:onCreate()--override" << endl;
}
//纯虚函数的实现
int getLayoutID(){
return 1;
}
};
class PersonActivity : public BaseActivity {
public:
//重写了:动态多态
void onCreate() {
cout << "PersonActivity:onCreate()" << endl;
}
//纯虚函数的实现
int getLayoutID(){
return 2;
}
};
void gotoActivity(BaseActivity *baseActivity) {
baseActivity->onCreate();
}
int main(){
BaseActivity * homeActivity = new HomeActivity();
BaseActivity * personActivity = new PersonActivity();
gotoActivity(homeActivity);
gotoActivity(personActivity);
delete homeActivity;
delete personActivity;
return 0;
}
本章内容是非常非常重要的,一定要熟记熟用。。。。。。
本章内容是非常非常重要的,一定要熟记熟用。。。。。。
本章内容是非常非常重要的,一定要熟记熟用。。。。。。
网友评论