C++面向对象速览(一)

感谢黑马开源!

一,重载函数

(同一作用域,相同名称,不同参数的函数)

注意事项:

1,(引用/指针)也可以作为重载的条件

传递方式 是否可以区分 const 原因
值传递 ❌ 不能 const 只影响函数内部,不影响调用时的匹配。
引用传递 ✅ 能 int&const int& 是不同的类型,可以绑定不同的实参。
指针传递 ✅ 能 int*const int* 是不同的类型,可以指向不同的数据。

关于左值,右值另有高论,参考:深入浅出C++左值与右值 ------ 一个视频彻底搞懂左值与右值!哔哩哔哩bilibili

2,注意默认参数导致的报错

二,类与封装

访问权限相关18

class和struct区别19

默认访问权限,s公有,c私有。

读写控制set/get20

立方体实例21

文件关系22

点和圆关系为例子,将类的声明放在头文件中,将类的实现放在主文件中!

方式 优点 缺点
#pragma once 简洁,不易出错 非标准(但几乎所有现代编译器都支持)
#ifndef 宏保护 标准 C/C++,兼容性强 需要手动确保宏名唯一,代码稍显冗长

初识构造函数与析构函数23

构造函数:

1,名同类名,可以有参数,可以重载,对象实例化时自动调用,编译器会在没有设置构造函数时,自动添加一个空构造函数。

2,只会调用一次。

析构函数:

1,~名同类名,无参无构造,不可重载,对象销毁前(出栈)自动调用。编译器会在没有设置析构函数时,自动添加一个空析构函数。

2,只会调用一次,写在main函数中时,会在main函数结束时销毁。

构造函数的分类和调用24

1,按照有无参数分类:有参构造,无参构造

2,按照参数类型分类:普通构造,拷贝构造

拷贝构造传参为常量类对象的引用,可以拷贝出一个和该对象相同的对象。

构造函数的调用方法:

1,括号法

2,显示法

3,隐式转换法

简单写下代码

scss 复制代码
class Person{
  private:
    int age;
  public:
    //constructor
    //Parameterless Construction
    Person(){
        age = 0;
    }
    //Parametrical Construction
    Person(int a){
        age = a;
    }
    //Copy Construction
    Person(const Person &p1){
        age = p1.age;
    }
    
};
​
void test01{
    //bracket call
    Person p;
    Person p1(10);
    Person p2(p);
    //tips:
    (X)Person p1();
    //In this way , the compiler will evaluates "Person p1()" to a func return type Person.
    
    //display call
    Person p3;
    Person p4 = Person(10);
    Person p5 = Person(p4);
    //anonymous object will destroy after this line call.
    Person(12);
    //tips:
    (x)Person(p5);
    //We can't initialize anonymous object in Copy Construction.
    
    //Implicit Conversion
    Person p6;
    Person p7 = 10;
    Person P8 = p7;
}

拷贝构造时机25

1,使用一个创建完成的类对象来初始化一个新对象

2,值传递给函数参数传值

3,类对象做返回值(以值方式返回局部对象)

scss 复制代码
tesr01{
    Person p1(10);
    Person p2(p1);
}
​
test02(Person p){
    Person p3(p);
}
​
Person test03(){
    //
    return Person p;
}
​

构造函数调用规则26

一个类定义时,系统自动提供三种构造函数。

1,用户自定义有参,系统不自动提供无参

2,用户自定义拷贝,系统不自动提供其他

拷贝构造的浅拷贝与深拷贝27

类默认提供的拷贝构造是浅拷贝,只将类成员变量的值复制给要实例化的对象。在类中有指针成员变量时,浅拷贝只会传递内存地址,在析构函数中会触发堆区内存重复释放的错误,

ini 复制代码
class Person{
    public:
    int age;
    int *h;
    
    Person(const Person p){
        age = p.age;
        //deep copy
        int h = new int(*p.h);
    }
    
    ~Person(){
        if(h != NULL){
            delete h;
        }
        h = NULL;
    }
};
​

构造函数初始化列表28

arduino 复制代码
int ca;
int cb;
int cc;
​
Person(int a,int b,int c) : aa(a),cb(b),cc(c){}

其他类对象做类的成员,构造/析构顺序29

先调用其他类的构造,最后调用其他类的析构

typescript 复制代码
class Phone{
   string pname;
   phone (string name):pname(name){}
} ;
​
class Person{
    string hname;
    Phone pname;
    //Phone pname = phone
    //Implicit Conversion
    Person(string person, string phone):hname(person),pname(phone){}
}

静态成员函数与静态成员变量30&31

1,静态成员函数和静态成员变量都有访问权限

静态成员变量:

1,所有类对象公用的变量(共用一份数据)

2,在编译阶段分配内存

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

对于第三点,我进行了一些尝试,结果是,必须在类外初始化。

如果尝试在定义时初始化,则语法报错提示,如果需要初始化静态成员变量,则该变量必须是常量。

如果只在构造时初始化,则编译后(build error)报错:

LNK2001 unresolved external symbol "public: static int Student::Sch_s"

所以在类外做初始化是必要的!

c 复制代码
class Student {
public:
    static int Sch_s ;
    static string Sch_n;
    int Xh = 10000;
    string stu_name = "Lim";
    Student() {
        Sch_s++;
    }
​
    Student(int xh, string name) :Xh(xh), stu_name(name) {
        Sch_s++;
    }
    
    static void ChangeSchName(string name){
        Sch_n = name;
        cout<<"This School change name to "<<name<<endl;
    }
    
    void show() {
        cout<<"The school name is "<<Sch_n<<endl;
        
        cout << "Name  :" << stu_name << "   XueHao  :" << Xh << endl;
        cout << "Now School has " << Sch_s << "Students" << endl;
    }
​
};
​
int Student::Sch_s = 0;
string Student::Sch_n = "XiWang";
int main() {
    Student s1;
    Student s2(10001, "miss");
    s1.show();
    s1.ChangeSchName("GuangMing");
    s2.show();
}

静态成员函数:

1,所有类对象共用一个静态成员函数。

2,静态成员函数只能访问静态成员变量。

静态成员函数不能访问非静态成员变量的原因是:

静态成员函数分不清非静态成员变量到底是哪一个对象的变量。

C++对象特性(模型)和this指针之章

成员变量和成员函数分开存储32

通过sizeof检查大小发现,C++编译器会给每个空对象分配一个字节空间,为了区分空对象占用内存的位置。只有类的非静态成员变量在类的对象上,用sizeof可以检查到空间占用。

也就是说,类的非静态成员函数,类的静态成员变量,类的静态成员函数都不在类的对象上。

this指针用途(链式编程思想)33

this指针用途:

1,解决名称冲突

解决形参列表和类成员变量重名的冲突

2,返回对象本身引用

this指针指向被调用的成员函数所属的对象,可以用于在类的非静态成员函数中返回对象本身(引用方式)。

如果在下面的例子中不使用引用的方式,则每次调用add函数只会返回一个对于篇

的拷贝构造,实际上后续的修改没有修改到p2上,所以最终的值为20。

scss 复制代码
class Person{
    int age;
    person(int age){
        //age = age;
        this->age = age;
    }
    //Person
    Person& personAddAge(Person &p){
        this->age += p.age;
        return *this;
    }
};
​
void test01(){
    Person p1(18);
}
​
void test02(){
    Person p1(10);
    Person p2(10);
    p2.personAddAge(p1).personAddAge(p1).personAddAge(p1);
}

空指针访问类的成员函数34

空类指针(同this指针)可以访问类的成员函数。

类成员函数中使用到类成员变量//时,会自动在前面加上this指针,所以空指针无法取到该成员变量的值会报错。

c 复制代码
class Person{
    int m_age;
    showPersonAge(){
        //cout<<this->age;
        cout<<m_age;
    }  
};

const修饰成员函数35

this补充:

1,this 指针隐含在每一个非静态成员函数之中

2,this 指针不需要定义,直接使用即可

常函数:

1,成员函数后加const后是常函数

2,常函数内不能修改成员属性

3,成员属性声明时加关键字mutable后,在常函数中可以修改

常对象:

1,声明对象前加const的对象是常对象

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

csharp 复制代码
class Person{
    public:
    (x)void theEssenceOfThis(){
        this = NULL;
    }
    //Can't change point to(address) also can't change the point to value
    //const Person * const this
    void constantFunc() const{
        //Variables that are not mutable cannot be modified.
        //this->m_a = 100;
        this->m_b = 100;
    }
    
    int m_a;
    mutable int m_b;
};
​
void test01(){
    Person p;
    //this is Pointer Constant,Can't change point to
    //this(Person * const this)
    p.theEssenceOfThis();
}
​
void test02(){
    Person p;
    p.constantFunc();
}
​
//constant obj
void test03(){
    const Person p;
    //p.m_a = 100;
    p.m_b = 100;
    //constant obj can just call constant func
    p.constantFunc();
}

友元36

1,全局函数做友元,可以访问类的私有部分。

csharp 复制代码
class Building{
    //pass by address , avoid the cost of memory
    friend void frifunc(Building * building);
    public:
        Building(){
            this->livingroom = "keting";
            this->bedroom = "woshi";
        }
    public:
        string livingroom;
    private:
        string bedroom;
};
​
void frifunc(Building* building){
    cout<<building.livingroom;
    cout<<building.bedroom;
}
​
int main(){
    Building b;
    frifunc(&b);
    return 0;
}

关于类指针的思考

表达式 含义 地址类型
l1 指针存储的地址(指向堆上的 Liter 对象) 堆地址
&l1 指针变量 l1 本身的地址(在栈上) 栈地址
  • l1 是动态分配的对象的地址(堆)。
  • &l1 是指针变量本身的地址(栈)。
  • delete l1 释放堆内存,但不影响 l1 的栈地址。
ini 复制代码
#include<iostream>
using namespace std;
​
class Liter {
public:
    char a, b, c;
    Liter(char a, char b, char c) {
        this->a = a;
        this->b = b;
        this->c = c;
    }
};
​
int main() {
    Liter *l1 = new Liter('a','b','c');
    cout << l1 << endl;
    cout << &l1 << endl;
    //000002143D4A7EC0
    //0000009942EFFB18
    delete l1;
    l1 = nullptr;
    return 0;
}

友元类37

注意,友元关系是一种 "访问授权" ,而不是 "继承授权"。所以没有继承友元类这样的说法。

类做友元,可以访问类的私有部分。

arduino 复制代码
class Friend{
public:
    Friend();
    void visit();
    Building * building;
}
​
​
class Building{
    
    
    //
    friend class Friend;
    
    //pass by address , avoid the cost of memory
    friend void frifunc(Building * building);
    public:
        Building(){
            this->livingroom = "keting";
            this->bedroom = "woshi";
        }
    public:
        string livingroom;
    private:
        string bedroom;
};
​
//member func realize out of class
​
Friend::Friend(){
    building = new Building;
}
​
void Friend::visit(){
    building->livingroom = "ke";
    building->bedroom = "wo";
}
​
​

成员函数做友元38

arduino 复制代码
class Building{
    friend void Friend::visit();  
    
};

由于超出掘金最大字数限制,我将分p发布。

相关推荐
Merokes5 小时前
关于Gstreamer+MPP硬件加速推流问题:视频输入video0被占用
c++·音视频·rk3588
请来次降维打击!!!7 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
别NULL7 小时前
机试题——统计最少媒体包发送源个数
c++·算法·媒体
嘤国大力士7 小时前
C++11&QT复习 (七)
java·c++·qt
背影疾风7 小时前
C++学习之路:指针基础
c++·学习
x-cmd7 小时前
[250331] Paozhu 发布 1.9.0:C++ Web 框架,比肩脚本语言 | DeaDBeeF 播放器发布 1.10.0
android·linux·开发语言·c++·web·音乐播放器·脚本语言
myloveasuka8 小时前
[Linux]从硬件到软件理解操作系统
linux·开发语言·c++
UpUpUp……8 小时前
特殊类的设计/单例模式
开发语言·c++·笔记·单例模式
苏克贝塔8 小时前
CMake学习--Window下VSCode 中 CMake C++ 代码调试操作方法
c++·vscode·学习
嘤国大力士8 小时前
C++11&QT复习 (十一)
开发语言·c++·qt