视频37——高级强制类型转换
#include <iostream>
using namespace std;
#include <string>
基类
class Company
{
public:
//构造器
Company(string theName,string product);
//方法
virtual void printInfor();//打印信息
protected:
string name;
string product;
};
//基类构造器实现
Company::Company(string theName,string product)
{
name = theName;
this->product = product;
}
//基类方法实现
void Company::printInfor()
{
cout << "这家公司的名字叫:" << name << "正在生产" << product << endl;
}
子类
class TechCompany:public Company
{
public:
//构造器
TechCompany(string theName, string product);
//方法
void printInfor();//打印信息
};
//构造器实现
TechCompany::TechCompany(string theName, string product):
Company(theName, product)
{
}
//方法实现
void TechCompany::printInfor()
{
cout << name << "公司大量生产了" << product << "\n\n";
}
int main()
{
Company *company = new TechCompany("苹果", "IPHONE");
//将Company类型强制转换为TechCompany类型
TechCompany *techCompany = (TechCompany*)company;
techCompany->printInfor();
//释放内存(此处company与techCompany两个指针都指向TechCompany定义的对象)
//所以释放内存只需要释放一次即可[注意不能停同时删除这两个!!!]
delete company;//删除指针地址
company = NULL;//为指针指向的地址赋空值
return 0;
}
动态对象强制类型转换
#include <iostream>
using namespace std;
#include <string>
基类
class Company
{
public:
//构造器
Company(string theName,string product);
//方法
virtual void printInfor();//打印信息
protected:
string name;
string product;
};
//基类构造器实现
Company::Company(string theName,string product)
{
name = theName;
this->product = product;
}
//基类方法实现
void Company::printInfor()
{
cout << "这家公司的名字叫:" << name << "正在生产" << product << endl;
}
子类
class TechCompany:public Company
{
public:
//构造器
TechCompany(string theName, string product);
//方法
void printInfor();//打印信息
};
//构造器实现
TechCompany::TechCompany(string theName, string product):
Company(theName, product)
{
}
//方法实现
void TechCompany::printInfor()
{
cout << name << "公司大量生产了" << product << "\n\n";
}
int main()
{
Company *company = new Company("苹果", "IPHONE");
//Company和TechCompany虽然结构相同,但是属于两个不同对象
TechCompany *techCompany = dynamic_cast<TechCompany*>(company);
if(techCompany == NULL)
{
cout << "悲催!!!" << endl;
}
else
cout << "成功!!!" << endl;
//释放内存(此处company与techCompany两个指针都指向TechCompany定义的对象)
//所以释放内存只需要释放一次即可[注意不能停同时删除这两个!!!]
delete company;//删除指针地址
techCompany = NULL;
company = NULL;//为指针指向的地址赋空值
return 0;
}
视频38——避免内存泄漏
如果程序会运行很长时间(例如在服务器上,注意不是所有的操作系统都像windows一样每天都要重启),并且在不停地申请新的内存块,忘记释放那些已经不再有用的老内存迟早会把内存消耗殆尽,直接导致后边的new操作无法执行甚至崩溃。
内存作用域
视频39——命名空间和模块化编程
系统头文件
自定义头文件
Rational.h文件
//Ration.h
//Create by Xue
//这个头文件用来声明有理数类(Rational class)
//类里面对四则运算进行重载,以实现分数运算
#include <iostream>
//定义基类
class Rational
{
public:
//构造器
Rational(int num1, int den1);
//析构器
~Rational();
//方法
Rational operator + (Rational rhs);//rhs = right hand side(右边的参数)
Rational operator - (Rational ths);
Rational operator * (Rational ths);
Rational operator / (Rational ths);
private:
void normalize();//负责对分数的简化处理
int num;//分子
int den;//分母
//友元函数
friend ostream &operator << (ostream &os, Rational f);//对运算符<<重载
};
Rational.cpp文件
/** \brief
*
* 运算符"<<"重载实现有理数(分式)的加减乘除
*
*/
#include<iostream>
using namespace std;
#include<string>
#include<cmath>
#include "main.h"
//构造函数实现
Rational::Rational(int num1, int den1)
{
num = num1;
den = den1;
normalize();//对分数化为最简形式
}
//析构器的实现呢
Rational::~Rational()
{
}
//基类的方法实现
void Rational::normalize()
{
//normalize()对分数进行简化操作包括:
//1.只允许分子为负数,如果分母为负数则把负数挪到分子部分,如1/-2==-1/2
//2.利用欧几里德算法(辗转求余原理)将分数进行简化:2/10 => 1/5
if(den < 0)
{
den = -den;
num = -num;
}
//辗转求余原理:求解分子和分母的最大公约数
int a = abs(num);
int b = abs(den);
while(b > 0)
{
int t = a % b;
a = b;
b = t;
}
//分子,分母同时除以最大公约数
num = num / a;
den = den / a;
}
//分式加法运算
//a c a*d c*b a*d + c*d
//- + - = --- + --- = ----------
//b d b*d b*d b*d
Rational Rational::operator + (Rational rhs)
{
int e,f;
e = num * rhs.den + rhs.num * den;
f = den * rhs.den;
return Rational(e,f);
}
//分式减法运算【转化为加法运算】
//a c a -c
//- - - = - + --
//b d b d
Rational Rational::operator - (Rational rhs)
{
rhs.num = -rhs.num;
return operator + (rhs);
}
//分式乘法运算
//a c a*c
//- * - = ---
//b d b*d
Rational Rational::operator*(Rational rhs)
{
int e,f;
e = num * rhs.num;
f = den * rhs.den;
return Rational(e,f);
}
//分式除法运算
//a c a d
//- / - = - * -
//b d b c
Rational Rational::operator/(Rational rhs)
{
int e,f;
e = num * rhs.den;
f = den * rhs.num;
return Rational(e,f);
}
//函数声明
//并不属于Rational类,是一个独立的函数
ostream &operator << (ostream &os, Rational f);
int main()
{
Rational c1(3,4);
Rational c2(2,4);
//有理数加法验证
//第一、三、五个<<检测到后面c1是Rational类型,执行重载函数
//第二、四、六个<<检测到后面的“+”不是Rational类型,执行打印输出功能
cout << c1 << " + " << c2 << " == " << (c1+c2) << "\n";
//有理数减法验证
cout << "\n\n";
cout << c1 << " - " << c2 << " == " << (c1-c2) << "\n";
//有理数乘法验证
cout << "\n\n";
cout << c1 << " * " << c2 << " == " << (c1*c2) << "\n";
//有理数除法验证
cout << "\n\n";
cout << c1 << " / " << c2 << " == " << (c1/c2) << "\n";
return 0;
}
//并不属于Rational类,是一个独立的函数
ostream &operator << (ostream &os, Rational f)
{
if(f.num % f.den == 0)//此时分子是分母的倍数,打印整数
os << f.num / f.den;
else
os << f.num << "/" << f.den;//打印分数
return os;
}
视频40——命名空间和模块化编程2
eg: #include ".\\main.h"中的是该.h文件和.c文件在同一个目录下
在Liunx系统中是采用斜杠'/',但是在window系统中采用反斜杠‘\’,但是反斜杠‘\’在window中又表示转义字符,所以最终采用‘\\’。
预处理器的条件指令
利用C++预处理器,我们可以让头文件只在这个类还没有被声明过的情况下才声明它。作为一种固定模式,这里使用常量名通常与相应的文件名保持一致(换成大写),把句号替换为下划线。例如rational.h文件对应RATIONAL_H
Ration.h文件
//Ration.h
//Create by Xue
//这个头文件用来声明有理数类(Rational class)
//类里面对四则运算进行重载,以实现分数运算
//如果RATIONAL_H未被定义,则定义rational.h,执行定义类程序
//如果RATIONAL_H已经被定义,程序则直接跳到endif(即定义类程序只会执行一次)
#ifndef MAIN_H
#define MAIN_H
#include <iostream>
//定义基类
class Rational
{
public:
//构造器
Rational(int num1, int den1);
//析构器
~Rational();
//方法
Rational operator + (Rational rhs);//rhs = right hand side(右边的参数)
Rational operator - (Rational ths);
Rational operator * (Rational ths);
Rational operator / (Rational ths);
private:
void normalize();//负责对分数的简化处理
int num;//分子
int den;//分母
//友元函数
friend ostream &operator << (ostream &os, Rational f);//对运算符<<重载
};
#endif // MAIN_H
打印爱心fishc.h文件
//fish.h
//Create by Xue
//打印爱心
#ifndef FISHC_H
#define FISHC_H
#include <iostream>
using namespace std;
//输出爱心
void call_love_fishc()//输出爱心
{
int i,j;
int n = 10;
for(i=1-(n>>1);i<=n;i++)//>>右移,右移一位除以2,左移一位乘以2
{
cout << "Hello World!";
if(i>=0)
{
for(j=0;j<i;j++)
cout << " ";
for(j=1;j<=2*(n-i)+1;j++)
cout << " *";
cout << endl;
}
else
{
for(j=i;j<0;j++)
cout << " ";
for(j=1;j<=n+2*i+1;j++)
cout << " *";
for(j=1;j<=-1-2*i;j++)
cout << " ";
for(j=1;j<=n+2*i+1;j++)
cout << " *";
cout << endl;
}
}
}
#endif // FISHC_H
Ration.cpp文件
#include<iostream>
using namespace std;
#include<string>
#include<cmath>
#include ".\\main.h"//该.h文件和.c文件在同一个目录
//构造函数实现
Rational::Rational(int num1, int den1)
{
num = num1;
den = den1;
normalize();//对分数化为最简形式
}
//析构器的实现呢
Rational::~Rational()
{
}
//基类的方法实现
void Rational::normalize()
{
//normalize()对分数进行简化操作包括:
//1.只允许分子为负数,如果分母为负数则把负数挪到分子部分,如1/-2==-1/2
//2.利用欧几里德算法(辗转求余原理)将分数进行简化:2/10 => 1/5
if(den < 0)
{
den = -den;
num = -num;
}
//辗转求余原理:求解分子和分母的最大公约数
int a = abs(num);
int b = abs(den);
while(b > 0)
{
int t = a % b;
a = b;
b = t;
}
//分子,分母同时除以最大公约数
num = num / a;
den = den / a;
}
//分式加法运算
//a c a*d c*b a*d + c*d
//- + - = --- + --- = ----------
//b d b*d b*d b*d
Rational Rational::operator + (Rational rhs)
{
int e,f;
e = num * rhs.den + rhs.num * den;
f = den * rhs.den;
return Rational(e,f);
}
//分式减法运算【转化为加法运算】
//a c a -c
//- - - = - + --
//b d b d
Rational Rational::operator - (Rational rhs)
{
rhs.num = -rhs.num;
return operator + (rhs);
}
//分式乘法运算
//a c a*c
//- * - = ---
//b d b*d
Rational Rational::operator*(Rational rhs)
{
int e,f;
e = num * rhs.num;
f = den * rhs.den;
return Rational(e,f);
}
//分式除法运算
//a c a d
//- / - = - * -
//b d b c
Rational Rational::operator/(Rational rhs)
{
int e,f;
e = num * rhs.den;
f = den * rhs.num;
return Rational(e,f);
}
//并不属于Rational类,是一个独立的函数
ostream &operator << (ostream &os, Rational f)
{
if(f.num % f.den == 0)//此时分子是分母的倍数,打印整数
os << f.num / f.den;
else
os << f.num << "/" << f.den;//打印分数
return os;
}
main.cpp文件
#include <iostream>
using namespace std;
#include "main.h"
#include <string>
#include <math.h>
#include "fichc.h"
int main()
{
call_love_fishc();//输出爱心
Rational c1(3,4);
Rational c2(2,4);
//有理数加法验证
//第一、三、五个<<检测到后面c1是Rational类型,执行重载函数
//第二、四、六个<<检测到后面的“+”不是Rational类型,执行打印输出功能
cout << c1 << " + " << c2 << " == " << (c1+c2) << "\n";
//有理数减法验证
cout << "\n\n";
cout << c1 << " - " << c2 << " == " << (c1-c2) << "\n";
//有理数乘法验证
cout << "\n\n";
cout << c1 << " * " << c2 << " == " << (c1*c2) << "\n";
//有理数除法验证
cout << "\n\n";
cout << c1 << " / " << c2 << " == " << (c1/c2) << "\n";
return 0;
}
视频41——命名空间和模块化编程3
命名空间其实就是由用户定义的范围,同一个命名空间里的东西只要在这个命名空间里具有独一无二的名字就行了。
Rational.h文件
//Rational.h
//Create by Xue
//这个头文件用来声明有理数类(Rational class)
//类里面对四则运算进行重载,以实现分数运算
#ifndef RATIONAL_H
#define RATIONAL_H
#include <iostream>
namespace Myname
{
//定义基类
class Rational
{
public:
//构造器
Rational(int num1, int den1);
//析构器
~Rational();
//方法
Rational operator + (Rational rhs);//rhs = right hand side(右边的参数)
Rational operator - (Rational ths);
Rational operator * (Rational ths);
Rational operator / (Rational ths);
private:
void normalize();//负责对分数的简化处理
int num;//分子
int den;//分母
//友元函数
friend ostream &operator << (ostream &os, Rational f);//对运算符<<重载
};
}//这里没有“;”,不是类或结构体!!!
#endif // RATIONAL_H
Rational.cpp文件
/** \brief
*
* 运算符"<<"重载实现有理数(分式)的加减乘除
*
*/
#include<iostream>
using namespace std;
#include<string>
#include<cmath>
#include "Rational.h"
namespace Myname
{
//构造函数实现
Rational::Rational(int num1, int den1)
{
num = num1;
den = den1;
normalize();//对分数化为最简形式
}
//析构器的实现呢
Rational::~Rational()
{
}
//基类的方法实现
void Rational::normalize()
{
//normalize()对分数进行简化操作包括:
//1.只允许分子为负数,如果分母为负数则把负数挪到分子部分,如1/-2==-1/2
//2.利用欧几里德算法(辗转求余原理)将分数进行简化:2/10 => 1/5
if(den < 0)
{
den = -den;
num = -num;
}
//辗转求余原理:求解分子和分母的最大公约数
int a = abs(num);
int b = abs(den);
while(b > 0)
{
int t = a % b;
a = b;
b = t;
}
//分子,分母同时除以最大公约数
num = num / a;
den = den / a;
}
//分式加法运算
//a c a*d c*b a*d + c*d
//- + - = --- + --- = ----------
//b d b*d b*d b*d
Rational Rational::operator + (Rational rhs)
{
int e,f;
e = num * rhs.den + rhs.num * den;
f = den * rhs.den;
return Rational(e,f);
}
//分式减法运算【转化为加法运算】
//a c a -c
//- - - = - + --
//b d b d
Rational Rational::operator - (Rational rhs)
{
rhs.num = -rhs.num;
return operator + (rhs);
}
//分式乘法运算
//a c a*c
//- * - = ---
//b d b*d
Rational Rational::operator*(Rational rhs)
{
int e,f;
e = num * rhs.num;
f = den * rhs.den;
return Rational(e,f);
}
//分式除法运算
//a c a d
//- / - = - * -
//b d b c
Rational Rational::operator/(Rational rhs)
{
int e,f;
e = num * rhs.den;
f = den * rhs.num;
return Rational(e,f);
}
//函数声明
//并不属于Rational类,是一个独立的函数
ostream &operator << (ostream &os, Rational f)
{
if(f.num % f.den == 0)//此时分子是分母的倍数,打印整数
os << f.num / f.den;
else
os << f.num << "/" << f.den;//打印分数
return os;
}
}
int main()
{
Myname::Rational c1(3,4);
Myname::Rational c2(2,4);
//有理数加法验证
//第一、三、五个<<检测到后面c1是Rational类型,执行重载函数
//第二、四、六个<<检测到后面的“+”不是Rational类型,执行打印输出功能
cout << c1 << " + " << c2 << " == " << (c1+c2) << "\n";
//有理数减法验证
cout << "\n\n";
cout << c1 << " - " << c2 << " == " << (c1-c2) << "\n";
//有理数乘法验证
cout << "\n\n";
cout << c1 << " * " << c2 << " == " << (c1*c2) << "\n";
//有理数除法验证
cout << "\n\n";
cout << c1 << " / " << c2 << " == " << (c1/c2) << "\n";
return 0;
}
使用命名空间
视频42——链接和作用域
存储类(storage class):每个变量都有一个存储类,它决定着程序将把变量的值储存在计算机的什么地方、如何存储、以及变量应该有怎样的作用域。
PS:static变量可以有external或internal链接
链接
视频43——链接和作用域2
header.h头文件
#ifndef HEADER_H
#define HEADER_H
unsigned long returnFactorial(unsigned short num);
//不要再头文件里面定义变量,仅仅声明就OK
//实在要定义在前面加static const
static const unsigned short headerNum = 5;
#endif // HEADER_H
that.cpp文件
#include "header.h"
unsigned short thatNum = 8;
bool printMe = true;
unsigned long returnFactorial(unsigned short num)
{
unsigned short sum = 1;
for(int i = 1; i <= num; i++)
{
sum *= i;
}
if(printMe)
return sum;
else
return 0;
}
this.cpp文件
#include "header.h"
#include <iostream>
extern unsigned short thatNum;//表明为外链接
static bool printMe = false;//内链接,仅仅在该cpp文件使用
int main()
{
unsigned short thisNum = 10;
std::cout << thisNum << "! is equal to " << returnFactorial(thisNum) << "\n\n";
std::cout << thatNum << "! is equal to " << returnFactorial(thatNum) << "\n\n";
std::cout << headerNum << "! is equal to " << returnFactorial(headerNum) << "\n\n";
if(printMe)
std::cout << "小甲鱼真丑!!!\n\n";
return 0;
}