• 9、C++高级语法


    一、面向对象基础

    1 - 面向对象定义

    • C++定义类:C++使用struct、class来定义一个类
    • struct和class区别
      • struct的默认成员权限是public
      • class的默认成员权限是private

    2 - 面向对象构造与析构

    • 让自定义的类像内置类型一样
      • 一个int型的变量,可以完成+、-、*、/、比较、输出、++等一系列操作
      • 如果现在有一个自定义的复数类型,那么它的操作应该什么样?
        • 我们希望可以像使用int一样自然的使用它,同时它对我们是一个黑盒,一种抽象
    //Complex.h
    #pragma once
    class Complex
    {
    public:
    	Complex();			// 默认构造函数
    	virtual ~Complex();	// 析构函数
    };
    
    //Complex.cpp
    #include "Complex.h"
    #include<iostream>
    using namespace std;
    
    Complex::Complex()
    {
    	cout << "Complex::Complex()" << endl;
    }
    
    Complex::~Complex()
    {
    	cout << "Complex::~Complex()" << endl;
    }
    
    //Test.cpp
    #include <iostream>
    #include "Complex.h"
    
    int main()
    {
    	Complex c;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述

    3 - 面向对象属性

    //Complex.h
    #pragma once
    class Complex
    {
    public:
    	Complex();			// 默认构造函数
    	Complex(double r, double i);
    	virtual ~Complex();	// 析构函数
    
    	double GetReal() const;
    	void SetReal(double d);
    	double GetImage() const;
    	void SetImage(double i);
    private:
    	double _real;          // 复数的实部
    	double _image;         // 复数的虚部
    };
    
    //Complex.cpp
    #include "Complex.h"
    #include<iostream>
    using namespace std;
    
    Complex::Complex()
    {
    	cout << "Complex::Complex()" << endl;
    }
    
    Complex::Complex(double r,double i)
    {
    	this->_real = r;
    	this->_image = i;
    }
    
    Complex::~Complex()
    {
    	cout << "Complex::~Complex()" << endl;
    }
    
    double Complex::GetReal() const { return _real; }
    void Complex::SetReal(double d) { _real = d; }
    double Complex::GetImage() const { return _image; }
    void Complex::SetImage(double i) { _image = i; }
    
    //Test.cpp
    #include <iostream>
    #include "Complex.h"
    
    using namespace std;
    
    int main()
    {
    	Complex c(1.0,2.0);
    	cout << c.GetReal() << endl;	// 1
    	cout << c.GetImage() << endl;	// 2
    	c.SetReal(2.0);
    	c.SetImage(3.0);
    	cout << c.GetReal() << endl;	// 2
    	cout << c.GetImage() << endl;	// 3
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    4 - +、=运算符重载

    //Complex.h
    
    #pragma once
    class Complex
    {
    public:
    	Complex();			// 默认构造函数
    	Complex(double r, double i);
    	virtual ~Complex();	// 析构函数
    
    	double GetReal() const;
    	void SetReal(double d);
    	double GetImage() const;
    	void SetImage(double i);
    
    	// 运算符重载
    	Complex operator+(const Complex& c);
    	Complex& operator=(const Complex& c);
    	Complex& operator+=(const Complex &c);
    
    
    private:
    	double _real;          // 复数的实部
    	double _image;         // 复数的虚部
    };
    
    //Complex.cpp
    #include "Complex.h"
    #include<iostream>
    using namespace std;
    
    Complex::Complex()
    {
    	_real = 0.0;
    	_image = 0.0;
    }
    
    Complex::Complex(double r, double i)
    {
    	this->_real = r;
    	this->_image = i;
    }
    
    Complex::~Complex()
    {
    	cout << "Complex::~Complex()" << endl;
    }
    
    double Complex::GetReal() const { return _real; }
    void Complex::SetReal(double d) { _real = d; }
    double Complex::GetImage() const { return _image; }
    void Complex::SetImage(double i) { _image = i; }
    
    Complex Complex::operator+(const Complex& c)
    {
    	Complex tmp;
    	tmp._real = _real + c._real;
    	tmp._image = _image + c._image;
    	return tmp;
    }
    
    
    Complex& Complex::operator= (const Complex& c)
    {
    	if (this != &c)
    	{
    		_real = c._real;
    		_image = c._image;
    	}
    	return *this;
    }
    
    Complex& Complex::operator+= (const Complex& c)
    {
    	_real += c._real;
    	_image += c._image;
    	return *this;
    }
    
    //Test.cpp
    #include <iostream>
    #include "Complex.h"
    
    using namespace std;
    
    int main()
    {
    	Complex a(3.0, 2.0);
    	Complex b(2.0, 3.0);
    	Complex c;
    	c = a + b;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    5 - 前置后置操作符

    //h
    	// 前置和后置++
    	Complex& operator++();   //前置++
    	Complex operator++(int); //后置++
    	Complex& operator--();   //前置--
    	Complex operator--(int); //后置--
    
    //cpp
    Complex& Complex::operator++ () // 前置++
    {
    	_real++;
    	_image++;
    	return *this;
    }
    
    Complex Complex::operator++ (int) // 后置++
    {
    	//Complex tmp(*this);
    	//_real++;
    	//_image++;
    	//return tmp;
    	return Complex(_real++, _image++);
    }
    
    Complex& Complex::operator--()   //前置--
    {
    	_real--;
    	_image--;
    	return *this;
    }
    
    Complex Complex::operator--(int) //后置--
    {
    	return Complex(_real--, _image--);
    }
    
    //test
    int main()
    {
    	Complex a(3.0, 2.0);
    	Complex e;
    	e = a++;
    	e = ++a;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在这里插入图片描述

    6 - 比较运算符重载

    //h
    	bool operator==(const Complex &c) const;
    	bool operator!=(const Complex &c) const;
    
    //cpp
    
    bool Complex::operator==(const Complex& c) const
    {
    	return (_real == c._real) && (_image == c._image);
    }
    
    bool Complex::operator!=(const Complex& c) const
    {
    	return !( (_real == c._real) && (_image == c._image) );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    二、拷贝构造

    1 - 拷贝构造调用时机1

    • 调用拷贝构造的原因:tmp是内部定义的对象,在栈上,出了函数后就会被销毁,C++会自动调用拷贝构造函数
      在这里插入图片描述
    • 自己重写拷贝构造
    //h
    	Complex(const Complex& x);	// 拷贝构造
    
    //cpp
    Complex::Complex(const Complex& c)
    {
    	_real = c._real;
    	_image = c._image;
    	cout << "Complex::Complex(const Complex& c)" << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 优化:避免产生临时对象,不调用拷贝构造
    Complex Complex::operator+(const Complex& c)
    {
    	//Complex tmp;
    	//tmp._real = _real + c._real;
    	//tmp._image = _image + c._image;
    	//return tmp;
    	return Complex(_real + c._real, _image + c._image);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 优化 —— Complex c = a + b:可以非常明显的看到减少了1次构造与析构
      在这里插入图片描述

    2 - 拷贝构造调用时机2

    在这里插入图片描述

    三、输入输出

    1 - 类重载输入输出运算符

    //h
    #pragma once
    #include <iostream>
    using namespace std;
    
    class Complex
    {
    public:
    	Complex();			// 默认构造函数
    	//省略...
    
    	friend ostream& operator<<(ostream& os, const Complex& x);
    	friend istream& operator>>(istream& is, Complex& x);
    
    private:
    	double _real;          // 复数的实部
    	double _image;         // 复数的虚部
    };
    
    //cpp
    ostream& operator<<(ostream& os, const Complex& x)
    {
    	os << "real value is  " << x._real << "  image value is " << x._image;
    	return os;
    }
    
    istream& operator >> (istream& is, Complex& x)
    {
    	is >> x._real >> x._image;
    	return is;
    }
    
    //test
    #include <iostream>
    #include "Complex.h"
    
    using namespace std;
    
    int main()
    {
    	Complex a(3.0, 2.0);
    	Complex e;
    	e = a++;
    	cout << e << endl;
    	e = ++a;
    	cout << e << endl;
    
    	cin >> e;
    	cout << e << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    2 - IO流

    • 传统的C中的IO流:函数有printf、scanf、getch、gets等函数,它们存在问题
      • 不可编程,仅仅能识别固有的数据类型
      • 代码的可移植性差,有很多的坑
    • C++中的IO流:istream、ostream,它们的优点
      • 可编程,对于类库的设计者来说很有用
      • 简化编程,能使得I/O的风格一致

    在这里插入图片描述

    2 - IO缓存区

    • 标准IO提供的三种类型的缓存模式
      • ①.按块缓存:如文件系统
      • ②.按行缓存:\n
      • ③.不缓存

    在这里插入图片描述

    • 缓冲区的验证
      • 使用清空缓存区脏数据的前后对比
        在这里插入图片描述

    四、文件操作

    1 - 文件介绍

    • 输入流的起点和输出流的终点:都可以是磁盘文件
    • C++中的文件:C++把每个文件都看成是一个有序的字节序列,每个文件都以文件结束标志结束
    • 按照文件中数据的组织形式可以把文件分为
      • 文本文件:文件中信息形式为ASCII码文件,每个字符占一个字节
      • 二进制文件:文件中信息的形式与其在内存中的形式相同
    • 文件操作步骤
      • ①.打开文件用于读或写open
      • ②.检查打开是否成功fail
      • ③.读或者写read,write
      • ④.检查是否读完EOF(end of file)
      • ⑤.使用完文件后关闭文件close
    • 文件打开方式
      • ios::in -> 打开文件进行读操作(ifstream默认模式);
      • ios::out -> 打开文件进行写操作(ofstream默认模式);
      • ios::ate -> 打开一个已有输入或输出文件并查找到文件尾;
      • ios::app -> 打开文件以便在文件的尾部添加数据;
      • ios::nocreate -> 如果文件不存在,则打开操作失败;
      • ios::trunc -> 如果文件存在,清除文件原有内容(默认);
      • ios::binary -> 以二进制方式打开;

    2 - 文本文件操作

    • 案例:文件流输入输出
    #include <iostream>
    #include "Complex.h"
    #include <fstream>
    
    using namespace std;
    
    int main()
    {
    	int a;
    	int index = 0;
    	fstream fout;
    	fout.open("testBuffer.txt", ios::app);
    	//if (fout.fail()) //等价
    	if (!fout)
    	{
    		cout << "open file failed" << endl;
    	}
    	while (cin >> a)
    	{
    		fout << "The numbers are: " << a << endl;
    		index++;
    		if (index == 5)
    		{
    			break;
    		}
    	}
    	cin.ignore(numeric_limits<std::streamsize>::max(), '\n');  // 清空缓存区脏数据
    	char ch;
    	cin >> ch;
    	fout << "the last char is: " << ch << endl;
    	fout.close();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述

    3 - 二进制文件操作

    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    static const int bufferLen = 2048;
    bool CopyFile(const string& src, const string& dst)
    {
    	// 打开源文件和目标文件
    	// 源文件以二进制读的方式打开
    	// 目标文件以二进制写的方式打开
    	ifstream in(src.c_str(), ios::in | ios::binary);
    	ofstream out(dst.c_str(), ios::out | ios::binary | ios::trunc);
    
    	// 判断文件打开是否成功,失败返回false
    	if (!in || !out)
    	{
    		return false;
    	}
    
    	// 从源文件中读取数据,写到目标文件中
    	// 通过读取源文件的EOF来判断读写是否结束
    	char temp[bufferLen];
    	while (!in.eof())
    	{
    		in.read(temp, bufferLen);
    		streamsize count = in.gcount();//从最后一次读取的长度
    		out.write(temp, count);
    	}
    
    	// 关闭源文件和目标文件
    	in.close();
    	out.close();
    
    	return true;
    }
    
    int main()
    {
    	cout << CopyFile("Blue Daube.mp3", "Blue Daube2.mp3") << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    五、头文件重复包含问题

    • 为了避免同一个文件被include多次,有两种方式:使用宏、使用编译器
    • 方案1:使用宏来防止同一个文件被多次包含
      • 优点:可移植性好
      • 缺点:无法防止宏名重复,难以排错
    #ifndef __SOMEFILE_H__
    #defind __SOMEFILE_H__
    ...
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 方案2:使用编译器来防止同一文件被多次包含#pragma once
      • 优点:可以防止宏名重复,易排错
      • 缺点:可移植性不好
    • 总结使用:如果只在windows使用使用方案2,其他使用方案1(注意宏不要重名)

    六、深拷贝、浅拷贝

    • 浅拷贝:只拷贝指针地址,C++默认拷贝构造函数与赋值运算符重载都是浅拷贝;节省空间,但容易引发多次释放

    • 深拷贝:重新分配堆内存,拷贝指针指向内容;浪费空间,但不会导致多次释放

    • h头文件

    #pragma once
    #include <iostream>
    using namespace std;
    
    class String
    {
    public:
    	String(const char* str = NULL);				// 普通构造函数
    	String(const String& other);                // 拷贝构造函数
    	String(String&& other);                     // 移动构造函数
    	~String(void);                              // 析构函数
    	String& operator= (const String& other);    // 赋值函数
    	String& operator=(String&& rhs)noexcept;	// 移动赋值运算符
    
    	friend ostream& operator<<(ostream& os, const String& c); // cout输出
    
    private:
    	char* m_data; // 用于保存字符串
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • cpp实现
    #include "String.h"
    
    
    // _CRT_SECURE_NO_WARNINGS
    
    // String 的普通构造函数
    String::String(const char* str)
    {
    	if (str == NULL)
    	{
    		m_data = new char[1];
    		if (m_data != NULL)
    		{
    			*m_data = '\0';
    		}
    		else
    		{
    			exit(-1);
    		}
    	}
    	else
    	{
    		int len = strlen(str);
    		m_data = new char[len + 1];
    		if (m_data != NULL)
    		{
    			strcpy(m_data, str);
    		}
    		else
    		{
    			exit(-1);
    		}
    	}
    }
    
    // 拷贝构造函数
    String::String(const String& other)
    {
    	int len = strlen(other.m_data);
    	m_data = new char[len + 1];
    	if (m_data != NULL)
    	{
    		strcpy(m_data, other.m_data);
    	}
    	else
    	{
    		exit(-1);
    	}
    }
    
    // 移动构造函数
    String::String(String&& other) //右值引用
    {
    	if (other.m_data != NULL)
    	{
    		// 资源让渡
    		m_data = other.m_data;
    		other.m_data = NULL;
    	}
    }
    
    
    // 赋值函数
    String& String::operator= (const String& other)
    {
    	if (this == &other)
    	{
    		return *this;
    	}
    	// 释放原有的内容
    	delete[] m_data;
    	// 重新分配资源并赋值
    	int len = strlen(other.m_data);
    	m_data = new char[len + 1];
    	if (m_data != NULL)
    	{
    		strcpy(m_data, other.m_data);
    	}
    	else
    	{
    		exit(-1);
    	}
    
    	return *this;
    }
    
    // 移动赋值运算符
    String& String::operator=(String&& rhs)noexcept
    {
    	if (this != &rhs)
    	{
    		delete[] m_data;
    		m_data = rhs.m_data;
    		rhs.m_data = NULL;
    	}
    	return *this;
    }
    
    // String 的析构函数
    String::~String(void)
    {
    	if (m_data != NULL)
    	{
    		delete[] m_data;
    	}
    }
    
    ostream& operator<<(ostream& os, const String& c)
    {
    	os << c.m_data;
    	return os;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 测试类
    #pragma once
    
    #include "String.h"
    using namespace std;
    
    
    int main()
    {
    
    	String s1("Hello");			// 构造函数
    	cout << s1 << endl;
    	//String s2 = s1;			// 调用拷贝构造函数
    	String s2(s1);				// 调用拷贝构造函数
    	cout << s2 << endl;
    	String s2A(std::move(s1));	// 移动构造函数
    	cout << s2A << endl;
    	String s3;					// 无参构造函数
    	cout << s3 << endl;
    	s3 = s2;					// 调用赋值函数
    	cout << s3 << endl;
    	String s3A;					// 无参构造函数
    	s3A = std::move(s2A);		// 移动赋值运算符
    	cout << s3A << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    七、虚函数

    #include <iostream>
    using namespace std;
    
    // 抽象类
    class Shape
    {
    public:
    	virtual double Area() const = 0;// 子类方法实现不一致加上virtual
    	virtual void Show() = 0;
    	void SetColor(int color) { _color = color; }
    	void Display()
    	{
    		cout << Area() << endl;
    	}
    private:
    	int _color;
    };
    
    class Square : public Shape
    {
    public:
    	Square(double len) :_len(len) { }
    	void Show() { cout << "Square" << endl; }
    	double Area() const
    	{
    		return _len * _len;
    	}
    private:
    	double _len;
    };
    
    
    class Circle : public Shape
    {
    public:
    	Circle(double radius) :_radius(radius) {}
    	void Show() { cout << "Circle" << endl; }
    	double Area() const
    	{
    		return 3.1415926 * _radius * _radius;
    	}
    
    private:
    	double _radius;
    };
    
    class Triangle : public Shape
    {
    public:
    	Triangle(double len, double height) :_len(len), _height(height) {}
    	void Show() { cout << "Triangle" << endl; }
    	double Area() const
    	{
    		return 0.5 * _len * _height;
    	}
    
    private:
    	double _len;
    	double _height;
    };
    
    int main()
    {
    	// 面对变化,尽可能少修改原有的逻辑,要扩充逻辑
    	const int shapeNum = 3;
    
    	Square s1(2.0);
    	s1.SetColor(1);
    	Circle   c1(2.0);
    	Triangle t1(2.0, 3.0);
    
    	Shape* shapes[shapeNum];
    	shapes[0] = &s1;
    	shapes[1] = &c1;
    	shapes[2] = &t1;
    
    	for (unsigned int index = 0; index < shapeNum; index++)
    	{
    		shapes[index]->Display();
    	}
    
    	cout << endl;
    	cout << sizeof(s1) << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
  • 相关阅读:
    SpringCloud——网关Gateway
    【Transformers】第 10 章:服务 Transformer 模型
    Redis的 延时双删以及数据一致性
    Vue3.2 + Element-Plus 二次封装 el-table(Pro版)
    9.19~9.20elf论文(浮点数的二进制表示&确定擦除尾随0的数量)
    Java 网络编程之TCP(五):分析服务端注册OP_WRITE写数据的各种场景(三)
    Vue之ElementUI之动态树+数据表格+分页(项目功能)
    【java】IO流
    计算机毕业设计ssm社区爱心活动网站be83l系统+程序+源码+lw+远程部署
    c语言第一周实验课
  • 原文地址:https://blog.csdn.net/qq23001186/article/details/125406579