c道核解--翊镜

本文介绍了C++中的对象访问权限,构造函数和析构函数的调用规则,包括无参构造、有参构造、拷贝构造。讨论了深拷贝和浅拷贝的区别,以及如何使用初始化列表。还涉及到了静态成员、内存管理和this指针的概念。此外,文章详细讲解了常量成员函数、友元机制、运算符重载的实现,以及继承、多态的基本概念,包括虚函数和抽象类。最后,阐述了文件的读写操作,包括文本和二进制模式。
摘要由CSDN通过智能技术生成

封装

一.对象的访问权限

默认的访问权限

1.struct默认为公开

2.class默认为私有

二.构造函数和析构函数

构造函数:初始化调用

类名{

}

析构函数:函数销毁时调用

~类名{

}

三.构造函数分类和调用

1.构造函数分类

-1.参数

有参构造

无参构造

-2.类型

普通构造

拷贝构造:需要传入一个相同类型的对象,复制这个对象的值到现有对象

2.构造函数调用

-1.括号法

Person p1;

Person p2(10);

Person p3(p2);

注意:默认构造不要加(),系统会认为是在声明

Person p1();

-2.显示法

Person p1;

Person p2=Person(10);

Person p3=Person(p2);

匿名对象

Person(10);

注意:不要用拷贝构造函数,初始化匿名对象,系统认为是Person(p3)===Person p3;

Person(p3);

3.隐式转换法

Person p4=10; //相当于Person p4=Person(10)

四.构造函数调用场景

1.使用已有对象初试化一个新对象

Person p3=Person(p2);

2.值传递的方式给函数参数传值

doWork(person p);

3.以值方式返回局部对象

Person doWork(){

Person p1;

return p1;

}

五.构造函数调用规则

1.默认函数

默认构造函数

默认析构函数

默认拷贝函数

2.用户定义有参构造,c++不会在提供默认无参构造,但会提供默认拷贝构造

3.用户定义拷贝构造函数,c++不会在提供其他构造函数

六.深拷贝和浅拷贝

1.浅拷贝

简单的复制拷贝操作

2.深拷贝

在兑取重新申请空间,进行拷贝操作

七.初始化列表属性(代替构造函数)

Person():m_A(10),m_B(20),m_C(30)

等价于

Person(int a,int b,int c){

this.a=a;

this.b=b;

this.c=c;

}

Person(a,b,c);

八.类对象成为类成员

1.将一个类作为属性创建在另一个类中

class A{}

class B{

A a;

}

2.顺序

A创建

B创建

B销毁

A销毁

九.静态成员

1.概念

静态成员就是在属性或函数前加static

2.特点

-静态成员变量

--所有对象共享同一份数据

--在编译阶段分配内存

--类内声明,类外初始化

-静态成员函数

--所有对象共享同一个函数

--静态成员函数只能访问静态成员变量

十.内存管理和this

1.类内成员变量和成员函数分开储存

只有非静态成员变量才属于类的对象上

2.this的用途

-1.因为在对象空间中,非静态变量会有多个实例化对象

利用this指向被调用的成员函数所属对象

-2.this是一个指针,*this 指向的是p2这个对象本体

十一.空指针调用成员函数

class Person

{

public:

void showage(){

cout<<""<<m_age;

}

int m_age;

}

void test(){

Person *p=NULL;

p->showage();

}

十二.const修士成员函数

常函数:

void showPerson() const{

}

相当于 const Person*this

左数右指

是一个常量指针,规定指向的值不可修改

1.成员函数后加const后我们称为这个函数为常函数

2.常函数内不可以修改成员属性

this的本质,指针常量,指针的指向不可修改,但指向的值可修改

3.成员属性声明是假关键词mutable后,在常函数中依然可以修改

常对象:

1.声明对象前加const成该对象为常对象

2.常对象只能调用常函数

十三.友元

实现访问私有变量

1.全局函数做友元

#include <iostream>

#include<string>

using namespace std;

class Building{

friend void ask(Building *a);

public:

Building(){

a="客厅";

b="卧室";

}

string a;

private:

string b;

};

void ask(Building *a){

cout<<a->b;

}

int main()

{

Building x;

ask(&x);

}

或者

void ask(Building &a){

cout<<a.b;

}

Building x;

ask(x);

引用的时候需要用.

指针用->

2.类做友元

friend class GoodGay;

3.成员函数做友元

friend void GoodGay::visit();

十四.运算符重载

1.加号运算符重载

实现两个自定义数据类型相加的运算

class Person

{

public:

int a;

int b;

};

//成员函数重载

Person operater+ (Person &p)

{

Person t;

t.a=this.a+p.a;

t.b=this.b+p.b;

return t;

}

Person p3=p1.operater(p2);

//等价于

Person p3=p1+p2;

//全局函数重载

#include <iostream>

#include<string>

using namespace std;

class Person

{

public:

int a;

int b;

};

Person operator+ (Person &p1,Person &p2)

{

Person t;

t.a=p1.a+p2.a;

t.b=p1.b+p2.b;

return t;

}

int main()

{

Person p1;

p1.a=10;

p1.b=10;

Person p2;

p2.a=10;

p2.b=10;

Person p3=p1+p2;

cout<<p3.a<<endl<<p3.b;

}

2.左移运算符重载

//成员函数重载

void operator<<(ostream&cout,Person &p){

cout<<p.a<<endl<<p.b;

}

//全局函数重载,需要实现友元,否则无法访问私有变量

ostream & operator<<(ostream&cout,Person &p){

cout<<p.a<<endl<<p.b;

return cout;

}

3.递增运算符重载

MyInteger& operator++(){

m_Num++;

return *this;

}

4.赋值运算符

Person& operator=(Person &p){

if(m_Age!=NULL){

delete m_Age;

m_Age=NULL;

}

m_Age=new int(*p.m_Age);

return *this;

}

5.关系运算符

bool operatpr==(Person &p){

if(this->m_name=p->m_name){

return ture;

}

return false;

}

6.函数调用运算符

void operator()(string test){

cout<<test<<endl;

}

-非常灵活,又叫仿函数

-可以实现各种功能

实例化对象

MyAdd myadd;

int ret =myadd(100);

匿名函数对象

MyAdd()(100,100);

继承

一.基础语法

class son:public father

{

public:

void content()

{

cout<<"对应内容";

}

};

二.继承方式

1.公共继承

2.保护继承

3.私有继承

三.继承中的对象模型

父类的私有类成员只是被隐藏了,但是还是被继承下来了

四.构造和析构顺序

1.父类构造

2.子类构造

3.子类析构

4.父类析构

五.访问同名成员

1.直接访问

s.a

s.func();

访问子类成员

2.加上作用域

s.Base::a

s.Base::func()

访问父类成员

六.访问同名静态成员

1.类内声明,类外赋值

2.实例化

Son s;

s.a

s.Base::a

s.func()

s.Base::func()

3.直接调用对象

Son::a

Son::Base::a

Son::Base::func()

七.多继承

class C:public A,public B

{

C c;

c.A::a;

c.B::a;

}

八.菱形继承

1.解决方式,通过虚继承解决

class Animal

{

public:

int a;

};

class Sheep: virtual public Animal{};

class Tuo: virtual public Animal{};

class SheepTuo:public Sheep,public Tuo{};

当我们使用虚继承时,SheepTuo的a只有一个,可以通过定义域修改,但是只看最后修改的值

两个指针,一个实际值

多态

一.静态多态和动态多态

1.静态多态

函数重载和运算符重载,复用函数名

2.动态多态

派生类和虚函数实现运行时多态

3.区别

静态多态的函数地址早绑定-编译

动态多态的函数地址晚绑定-运行

4.实例

//地址绑定

//倘若在animal的函数前加上virrus,那么结果就会变成 猫说话

#include<iostream>

using namespace std;

class Animal

{

public:

void speak()

{

cout<<"动物说话";

}

};

class Cat: public Animal

{

public:

void speak()

{

cout<<"猫说话";

}

};

void doSpeak(Animal &a)

{

a.speak();//输出 动物说话

}

int main()

{

Cat a;

doSpeak(a);

}

5.使用场景

-子类继承父类

-子类重写父类虚函数

二.多态原理剖析

1.虚函数表

重写覆盖虚函数表

二.纯虚函数和抽象类

1.因为父类的函数一般不会使用

所以将函数纯虚化

virtual void func()=0;

而纯虚函数所在的类又称为抽象类

2.限制

-无法实例化抽象类

-抽象类的子类,必须重写父类的纯虚函数,否则也无法实例化

三.虚析构和纯虚析构

1.多态使用时

如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码

2.解决方式:

将父类的析构函数改为虚析构或者纯虚析构

因为delete的是animal,所以会跳过

将父类的虚构函数虚化

Animal::~Animal()=0;

#include<iostream>

#include<string>

using namespace std;

class Animal

{

public:

virtual void speak()

{

cout<<"动物说话";

}

};

class Cat: public Animal

{

public:

Cat(string name)

{

m_name=new string(name);

}

virtual void speak()

{

cout<<*m_name<<"猫说话";

}

~Cat()

{

if(m_name!=NULL)

{

delete m_name;

m_name=NULL;

}

}

string *m_name;

};

int main()

{

Cat a("Tom");

a.speak();

}

3.纯虚析构需要声明,也需要实现

有了纯虚析构以后,这个类也属于抽象类

文件操作

一.写文件

1.包含头文件

#include <fstream>

2.创建流对象

ofstream ofs

3.打开文件

ofs.open("address",打开方式);

ios::in 读文件

ios::out 写文件

ofs.open("stest.txt",ios::out);

4.写数据

ofs<<"";

5.关闭文件

ofs.close();

二.读文件

1.包含头文件

#include <fstream>

2.创建流对象

ofstream ifs

3.打开

ifs.open("stest.txt",ios::in);

4.读数据

-第一种

char buf[1024]={0};

while(ifs>>buf)

{

cout<<buf<<endl;

}

-第二种

char buf[1024]={0};

while(ifs.getline(buf,sizeof(buf)))

{

cout<<buf<<endl;

}

-第三种

char buf;

while(ifs.getline(buf))

{

cout<<buf<<endl;

}

-第四种

char c;

while((c=ifs.get())!=EOF)

{

cout<<c;

}

5.关闭文件

ifs.close();

三.二进制读文件

1.包含头文件

#include <fstream>

2.创建流对象

ofstream ofs

3.打开文件

ofs.open("address",打开方式);

ios::in 读文件

ios::out 写文件

ofs.open("stest.txt",ios::out|ios::binary);

4.写数据

Perosn p;

ofs<<"";

ofs.write((const char*)p);

5.关闭文件

ofs.close();

四.二进制写文件

1.包含头文件

#include <fstream>

2.创建流对象

ofstream ifs

3.打开

ifs.open("stest.txt",ios::in|ios::binary);

4.读数据

Perosn p;

ifs.read((char*)&p,sizeof(Person));

cout<<p.m_Name<<p.m_Age<<endl;

5.关闭文件

ifs.close();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值