Day32.C++06
001.关系运算符重载(==)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(string name,int age)
{
this->m_Age = age;
this->m_Name = name;
}
//==运算符重载(!=运算符重载同理)
bool operator==(const Person& p)
{
if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
{
return true;
}
return false;
}
public:
string m_Name;
int m_Age;
};
void test01()
{
Person p1("小米", 10);
Person p2("小米", 10);//("小明", 9);
if (p1 == p2)
{
cout << "p1 和 p2 相等" << endl;
}
else
{
cout << "p1 和 p2 不相等" << endl;
}
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
002.函数调用运算符重载
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
//()重载
class myPrint
{
public:
void operator()(string text)
{
cout << text << endl;
}
};
void test01()
{
myPrint myprint1;
myprint1("hello world!!");
}
class myAdd
{
public:
int operator()(int val1, int val2)
{
return val1 + val2;
}
};
void test02()
{
//myAdd myadd;
//cout << myadd(1, 1) << endl;
cout << myAdd()(1, 1) << endl;//匿名对象
}
int main(void)
{
//test01();
test02();
system("pause");
return EXIT_SUCCESS;
}
003.强化训练_字符串的封装
总结:
- cout 输出自定义的字符串(<<重载)
- cin 让用户输入自定义的字符串内容(>>重载)
- = 、+ 、[] 、== 等运算符的重载
(代码)MyString.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
class MyString
{
friend ostream& operator<<(ostream& cout,MyString& str);
friend istream& operator>>(istream& cin, MyString& str);
public:
//有参构造
MyString(const char* str);
//拷贝构造
MyString(const MyString& str);
//析构函数
~MyString();
//=重载
MyString& operator=(const MyString& str);
MyString& operator=(const char* str);
//[]重载
char& operator[](int index);
//+重载
MyString operator+(const MyString& str);
MyString operator+(const char* str);
//==重载
bool operator==(const MyString& str);
bool operator==(const char* str);
private:
char* pString;//指向堆区的指针
int m_Size;//字符串大小
};
//左移运算符的重载
ostream& operator<<(ostream& cout,MyString& str);
//右移运算符的重载
istream& operator>>(istream& cin, MyString& str);
MyString.cpp
#include"MyString.h"
MyString::MyString(const char* str)
{
//cout << "有参构造调用" << endl;
this->pString = new char[strlen(str) + 1];
strcpy(this->pString, str);
this->m_Size = strlen(str);
}
MyString::MyString(const MyString& str)
{
//cout << "拷贝构造调用" << endl;
this->pString = new char[strlen(str.pString) + 1];
strcpy(this->pString, str.pString);
this->m_Size = str.m_Size;
}
MyString::~MyString()
{
//cout << "析构函数调用" << endl;
if (this->pString != NULL)
{
delete[] this->pString;
this->pString = NULL;
}
}
MyString& MyString::operator=(const MyString& str)
{
if (this->pString != NULL)
{
delete this->pString;
this->pString = NULL;
}
this->pString = new char[strlen(str.pString) + 1];
strcpy(this->pString, str.pString);
this->m_Size = str.m_Size;
return *this;
// TODO: 在此处插入 return 语句
}
MyString& MyString::operator=(const char* str)
{
if (this->pString != NULL)
{
delete this->pString;
this->pString = NULL;
}
this->pString = new char[strlen(str) + 1];
strcpy(this->pString, str);
this->m_Size = strlen(str);
return *this;
// TODO: 在此处插入 return 语句
}
char& MyString::operator[](int index)
{
return this->pString[index];
}
MyString MyString::operator+(const MyString& str)
{
//计算返回的字符串开辟的大小
int newSize = this->m_Size + strlen(str.pString) + 1;
char* tmp = new char[newSize];
memset(tmp, 0, newSize);
//拼接字符串
strcat(tmp, this->pString);
strcat(tmp, str.pString);
MyString newStr(tmp);
delete[] tmp;
tmp = NULL;
return newStr;
}
MyString MyString::operator+(const char* str)
{
//计算返回的字符串开辟的大小
int newSize = this->m_Size + strlen(str) + 1;
char* tmp = new char[newSize];
memset(tmp, 0, newSize);
//拼接字符串
strcat(tmp, this->pString);
strcat(tmp, str);
MyString newStr(tmp);
delete[] tmp;
tmp = NULL;
return newStr;
}
bool MyString::operator==(const MyString& str)
{
if (this->m_Size == str.m_Size)
{
if (!strcmp(this->pString, str.pString))
{
return true;
}
return false;
}
return false;
}
bool MyString::operator==(const char* str)
{
if (this->m_Size == strlen(str))
{
if (!strcmp(this->pString, str))
{
return true;
}
return false;
}
return false;
}
ostream& operator<<(ostream& cout,MyString& str)
{
cout << str.pString;
return cout;
// TODO: 在此处插入 return 语句
}
istream& operator>>(istream& cin, MyString& str)
{
//先判断原始是否有内容,如果有的话清空
if (str.pString != NULL)
{
delete str.pString;
str.pString = NULL;
}
//输入内容
char tep[1024];
cin >> tep;
//把输入的内容赋值给str
str.pString = new char[strlen(tep) + 1];
strcpy(str.pString, tep);
str.m_Size = strlen(tep);
return cin;
// TODO: 在此处插入 return 语句
}
强化训练_字符串的封装.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include"MyString.h"
using namespace std;
//测试MyString
void test01()
{
MyString str("abc");
cout << "str2 = " << str << endl;
//修改str里面的内容
/*cout << "请输入str新的内容: " << endl;
cin >> str;
cout << "新内容为: " << str << endl;*/
MyString str2(str);
MyString str3 = "";
str3 = str2;
cout << "str2 = " << str2 << " str3 = " << str3 << endl;
str2 = "aaaa";
str3[0] = 'w';
cout << "str2 = " << str2 << " str3 = " << str3 << endl;
cout << "str3 第一个位置为: " << str3[0] << endl;
MyString str4 = "";
//字符串拼接
str4 = str2 + str3;
str4 = str4 + "bbbb";
cout << "str4 = " << str4 << endl;
if (str4 == "aaaawbcbbbb")
{
cout << "str4 和 " << "aaaawbcbbbb" << "相等" << endl;
}
else
{
cout << "str4 和 " << "aaaawbcbbbb" << "不相等" << endl;
}
MyString str5 = "";
str5 = str4;
if (str4 == str5)
{
cout << "str4 和 str5 相等" << endl;
}
else
{
cout << "str4 和 str5 不相等" << endl;
}
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
004.继承的引出及继承方式
总结:
继承:减少代码的重复内容
语法:
class 派生类(子类):继承方式 基类(父类)
三种继承方式:
public :公有继承
private :私有继承
protected: 保护继承
- 三种继承方式都不可以访问父类的私有属性
- 公有继承:父类中的公共属性 和 保护属性 都不变
- 保护继承:父类中的公共属性 和 保护属性 都变为保护属性
- 私有继承:父类中的公共属性 和 保护属性 都变为私有属性
005.继承中的对象属性
子类中 会继承父类中的所有内容,包括私有成员
只是被编译器给隐藏起来,子类访问不到父类中的私有成员
006.继承中的构造和析构
总结:
子类创建对象时,先调用父类的构造,然后调用自己的构造
析构的顺序和构造顺序相反
子类会继承父类的成员属性,成员函数
但是子类不会继承父类的 构造函数 和 析构函数
(只有父类自己知道如何构造和析构自己的属性,而子类不知道)
如果父类中没有合适的默认构造,那么子类可以利用初始化列表的方式调用父类的其他构造
代码举例:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
cout << "Base默认构造函数调用" << endl;
}
~Base()
{
cout << "Base析构函数调用" << endl;
}
};
class Son :public Base
{
public:
Son()
{
cout << "Son默认构造函数调用" << endl;
}
~Son()
{
cout << "Son析构函数掉哦用" << endl;
}
};
void test01()
{
Son s;
}
class Base2
{
public:
Base2(int a)
{
this->m_A = a;
cout << "有参构造函数调用" << endl;
}
int m_A;
};
class Son_2 :public Base2
{
public:
Son_2(int a) :Base2(a)
{
}
};
void test02()
{
Son_2 s(10);
cout << s.m_A << endl;
}
int main(void)
{
test01();
//test02();
system("pause");
return EXIT_SUCCESS;
}
007.继承中的同名处理
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
this->m_A = 100;
}
public:
void func()
{
cout << "Base中的func的调用" << endl;
}
void func(int a)
{
cout << "Base中的func(int a)的调用" << endl;
}
int m_A;
};
class Son:public Base
{
public:
Son()
{
this->m_A = 200;
}
public:
void func()
{
cout << "Son中的func调用" << endl;
}
int m_A;
};
//如果子类和父类拥有同名的成员属性和函数,子类不会覆盖父类的成员
//如果子类和父类的成员函数的名称相同,子类会把父类所有的同名版本都隐藏掉
//想调用父类的方法,必须加作用域
void test01()
{
Son s;
cout << s.m_A << endl;
//打印父类中的m_A
cout << s.Base::m_A << endl;
//调用Son中的func
s.func();
//调用Base中的func
s.Base::func();
//调用Base中的func(int a)
//s.func(10);
s.Base::func(10);
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
008.继承中静态成员的处理
//类似继承中的同名处理
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Base
{
public:
static void func()
{
cout << "Base 的func()调用 " << endl;
}
static void func(int a)
{
cout << "Base 的func(int)调用 " << endl;
}
static int m_A;
};
int Base::m_A = 20;
class Son :public Base
{
public:
static int m_A;
static void func()
{
cout << "Son 中的func() 的调用" << endl;
}
};
int Son::m_A = 10;
//静态成员属性 子类可以继承下来
void test01()
{
cout << Son::m_A << endl;
cout << Base::m_A << endl;
Son::func();
Son::Base::func(10);
Base::func();
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
009.多继承的概念以及问题
- 多继承会引发二义性的问题
- 解决方法就是显示指定调用哪个基类的版本(即通过作用域区分)
010.菱形继承
菱形继承所带来的问题:
- 假设有一个动物类
- 羊类继承了动物类的属性;驼类也继承了动物类的属性
- 羊驼类既继承了羊类的属性,也继承了驼类的属性
- 第一个问题就是可能会产生二义性
- 第二个问题就是继承了动物类的函数和数据继承了两份,其实这份数据,我们只需要一份就可以了。
代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Animal
{
public:
int m_Age;
};
//虚基类 Sheep
class Sheep:virtual public Animal
{
public:
};
//虚基类 Tuo
class Tuo :virtual public Animal
{
public:
};
class SheepTuo :public Sheep, public Tuo
{
public:
};
//菱形继承的解决 利用虚继承
void test01()
{
SheepTuo sp;
sp.Sheep::m_Age = 10;
sp.Tuo::m_Age = 20;
cout << sp.Sheep::m_Age << endl;
cout << sp.Tuo::m_Age << endl;
cout << sp.m_Age <<endl;//可以直接访问,已经没有二义性的可能了,重复数据只有一份
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}