#include <iostream>
#include <cstring>
#include <string>
using namespace std;
class Box{
public:
Box(int h=10,int w=12,int len=15);// 声明有默认参数的构造函数
int volume();
~Box(){
cout << "调用了析构函数" << endl;
}
//使用对象作为函数参数不会影响实参 使用对象指针和对象引用才会影响实参
void addLength(Box &s){
s.length+=1;
}
// 静态数据成员若想在类外直接访问最后设为public
static int _count;// 静态数据成员只能在类外定义 只要是静态的数据成员只会更新一次,且只会保存最后的值 对于创建的静态对象只会被构造一次,且只会在程序全部结束后才会析构
// 拷贝函数
Box(const Box&);
// 静态成员函数 既可以在类外调定义,也可以在类外定义
static void Output();/*{
cout << _count << endl;
// cout << length <<endl; // 静态成员函数不能访问非静态数据成员
}*/
// 静态成员函数虽然不能直接访问非静态数据成员,但可以利用对象来间接访问它
// 因为其中带有个形参,会临时创建有个对象,则此成员函数结束就调用析构
static void f(Box m){
cout << "height:" << m.height <<endl;
cout << "width:" << m.width <<endl;
cout << "length:" << m.length <<endl;
cout << "volume:" << m.volume() << endl;
}
// 友元函数 可以访问类里面的一切
// 非成员函数作友元函数
friend void modifiedBox(Box& b,int height,int width,int length);
private:
int height;
int width;
int length;
};
// 类外定义一个友元函数
void modifiedBox(Box& b,int height,int width,int length){
cout << "修改box中的数据成员:" <<endl;
b.height=height;
b.width=width;
b.length=length;
}
// 在类外定义静态成员函数
void Box::Output(){
cout <<"静态成员函数的调用;"<< _count << endl;
}
// 在类外定义静态数据成员
int Box::_count=0;
// 类外定义
Box::Box(const Box& b){
height=b.height;
width=b.width;
length=b.length;
_count++;
}
Box::Box(int h,int w,int len):height(h),width(w),length(len){_count++;}
int Box::volume(){
return (height*width*length);
}
// 再定义一个类
class FangXi{
private:
char* _name;
int _s;
// 定义常量数据成员
const int _a;
// 定义静态常量数据成员
static const int _b;
public:
FangXi(char* name,int s,int a);
// 因为char* 类型动态创建了空间,所以要深拷贝
~FangXi();
FangXi(const FangXi& fa);
void Print();
};
// 静态常量数据成员跟静态非常量数据成员一样必须要在类外初始化!!!!不要忘写类名::
// 这个静态常量数据成员不能被修改
const int FangXi::_b=0;
// 类外定义
// 常量数据成员只能通过初始化列表进行!!!!!
FangXi::FangXi(char* name,int s,int a):_a(a){
int len=strlen(name)+1;
_name=new char[len];
strcpy(_name,name);
_s=s;
}
FangXi::~FangXi(){
// 调用深拷贝
cout << "调用深拷贝:" <<endl;
if(_name!=nullptr){
delete[] _name;
}
}
FangXi::FangXi(const FangXi& fa):_a(fa._a){
_s=fa._s;
int len=strlen(fa._name)+1;
_name=new char[len];
strcpy(_name,fa._name);
}
void FangXi::Print(){
cout << "名字:" << _name << " " << "大小:" << _s << " " << "常量数据成员_a:" << _a<<endl;
}
// 继承
class A{
private:
int a;
int b;
public:
A(int _a,int _b):a(_a),b(_b){
cout << "调用A的构造函数 " << endl;
}
};
class B:public A{
private:
int c;
// 定义有个内嵌数据成员
A x;
public:
B(int _a,int _b,int _c,int _aa,int _bb);
};
// 利用基类的构造函数来完成对基类数据成员的初始化
B::B(int _a,int _b,int _c,int _aa,int _bb):A(_a,_b),c(_c),x(_aa,_bb){
cout << "调用B的构造函数 " << endl;
}
// 运算符重载
class Person{
char *name; //存储姓名字符串的指针
char sex; //性别
char *address; //存储住址字符串的指针
public:
Person(const char* _name,char _sex,const char* _address);
~ Person();
Person(const Person& another);
Person& operator=(const Person& p);// 运算符重载
};
Person:: Person(const char* _name,char _sex,const char* _address){
int len1=strlen(_name)+1;
name=new char[len1];
memset(name,0,len1);
strcpy(name,_name);
sex=_sex;
int len2=strlen(_address)+1;
address=new char[len2];
memset(address,0,len2);
strcpy(address,_address);
}
Person::Person(const Person& another){
sex=another.sex;
int len1=strlen(another.name)+1;
name=new char[len1];
strcpy(name,another.name);
int len2=strlen(another.address)+1;
address=new char[len2];
strcpy(address,another.address);
}
Person::~Person(){
if (name!=NULL){
delete[] name;
}
if (address!=NULL){
delete[] address;
}
}
// 拷贝赋值函数
Person& Person::operator=(const Person& p){
int len1=strlen(p.name)+1;
name=new char[len1];
strcpy(name,p.name);
sex=p.sex;
int len2=strlen(p.address)+1;
address=new char[len2];
strcpy(address,p.address);
return *this;
}
// 对于重载运算符的规则:操作数的个数,优先级,结合性不能变
class Fraction {
int numerator; //分子
int denominator; //分母
public:
//构造函数的声明
Fraction();
Fraction(int n,int d);
//+,-,*,/运算符重载的声明
Fraction operator+(const Fraction& f) const;
Fraction operator-(const Fraction& f) const;
Fraction operator*(const Fraction&f) const;
Fraction operator/(const Fraction& f) const;
//+=的声明
Fraction& operator+=(const Fraction& f);
//前自增的声明,如果分数为a/b,则自增的结果是 a/b+1
Fraction& operator++();
//后自增的声明
Fraction operator++(int);
//关系运算符 >,==的声明
bool operator>(const Fraction& f) const;
bool operator==(const Fraction& f) const;
//double转换符的声明
operator double() const;
//<<运算符函数的声明
friend ostream& operator<<(ostream& o,const Fraction& f);
};
Fraction::Fraction():numerator(0),denominator(1){}
Fraction::Fraction(int n,int d):numerator(n),denominator(d){}
Fraction Fraction::operator+(const Fraction& f) const{
Fraction temp;
temp.denominator=denominator*f.denominator;
temp.numerator=denominator*f.numerator+numerator*f.denominator;
return temp;
}
Fraction Fraction::operator-(const Fraction& f) const{
Fraction temp;
temp.numerator=numerator*f.denominator-denominator*f.numerator;
temp.denominator=denominator*f.denominator;
return temp;
}
Fraction Fraction::operator*(const Fraction&f) const{
Fraction temp;
temp.numerator=numerator*f.numerator;
temp.denominator=denominator*f.denominator;
return temp;
}
Fraction Fraction::operator/(const Fraction&f) const{
Fraction temp;
temp.numerator=numerator*f.denominator;
temp.denominator=denominator*f.numerator;
return temp;
}
Fraction& Fraction::operator+=(const Fraction& f){
numerator=numerator*f.denominator+denominator*f.numerator;
denominator=denominator*f.denominator;
return *this;
}
Fraction& Fraction::operator++(){
numerator+=denominator;
return *this;
}
Fraction Fraction::operator++(int){
Fraction temp=*this;
numerator+=denominator;
return temp;
}
bool Fraction::operator>(const Fraction& f)const{
return (numerator*f.denominator)>(denominator*f.numerator);
}
bool Fraction::operator==(const Fraction& f) const{
return (numerator*f.denominator)==(denominator*f.numerator);
}
Fraction::operator double()const{
return numerator/denominator;
}
ostream& operator<<(ostream& o,const Fraction& f){
o<<f.numerator<<"/"<<f.denominator<<endl;
return o;
}
// 至少有一个纯虚函数的类叫抽象类,即抽象基类
// 其中抽象类的派生类分为直接派生类:基类就是抽象类;间接派生类:基类不是抽象类
// 虚函数
class M{
public:
// 定义为虚函数
// 非类的成员函数不能定义为虚函数
// 类的静态成员函数和构造函数不能定义为虚函数,但是析构函数都可以定义为虚函数
// 虚函数一般不被声明为内联函数
virtual void show();
// 定义虚析构函数
virtual ~M(){}
// 定义一个纯虚函数
virtual string area()=0;
private:
string name;
};
class N:public M{
public:
// 因为定义了虚函数,则对于基类的指针或者引用指向派生类的对象时,可以访问派生类的同名函数
void show();
// 因为定义了虚析构函数,则在delete运算符撤销对象时系统会先执行派生类的析构函数,然后执行基类的析构函数,完成彻底的“清理任务”
~N(){}
// 虚函数必须与纯虚函数的名字以及返回类型完全一样
virtual string area();
private:
int m;
};
int main()
{
Box a[3]=
{// 定义对象数组
Box(),
Box(15,18,20),
Box(16,20,26)
};
cout << "_count:" << Box::_count <<endl;
for(int i=0;i<3;i++){
cout << "volume:" << a[i].volume() <<endl;
}
// 使用对象指针
for(int i=0;i<3;i++){
Box *b;
b=&a[i];
cout << "指针 volume:" << b->volume() <<endl;
}
// 也可使用new运算符动态建立堆对象
Box *box;
box=new Box(10,20,30);
cout << "动态创建:" <<box->volume() <<endl;
box->addLength(*box);
cout << "addafter:" <<box->volume() <<endl;
cout << "_count:" << Box::_count <<endl;
// 最后不要忘记删除
delete box;
cout << "_count:" << Box::_count <<endl;
// 使用默认参数
Box box1;
cout << "_count:" << Box::_count <<endl;
Box box2(box1);
cout << "box1:" << box1.volume() << endl;
cout << "box2:" << box2.volume() << endl;
cout << "_count:" << Box::_count <<endl;
// 因为静态数据成员属于类,而不属于任何应该对象 则既可以通过类名来访问,也可以通过对象来访问
cout << "box1 _count:" << box1._count <<endl;
// 调用静态成员函数
Box::Output();
cout << "利用对象调用静态成员函数:";
box1.Output();
Box::f(box1);
modifiedBox(box1,10,20,20);
cout << "_count:" << Box::_count <<endl;
box1.f(box1);
cout << "_count:" << Box::_count <<endl;
FangXi fa("长方形",20,20);
fa.Print();
//定义常量对象
//常量类型定义之后就不能修改,除了常量指针和指针常量
const FangXi fa1("小黑子方型",520,10);
FangXi const fa2("小鸟何嗲咯",250,10);
// 常量对象不能修改数据成员,不能调用类的非常量成员函数,常量成员函数也不能调用非常量的成员函数
// fa1.Print
// 先调用基类的构造函数,然后是内嵌对象的构造函数,最后才是派生类的
// 对于有多个内嵌对象,只与其声明的顺序的顺序有关;
// 如果是多重继承,则基类的构造顺序看定义派生类时继承基类的顺序
// 二义性可以用作用域标识符::来消除
B ba(1,2,3,11,22);
// class A:virtual public B{....};//这个是虚基类,与多重继承相似在看虚基类的构造顺序时看定义派生类时继承虚基类的顺序
// 反正是先调用虚基类,再调用非虚基类,
// 而虚基类也可以由非虚基类派生,例如:class B:public C{...}; 其中之前已经确认B是虚基类,而C不是,则先调用C,然后B,最后C
// 赋值兼容原则
// 派生类的对象可以赋值给基类对象:Derived d; Base b; b=d;
// 派生类的对象可以初始化基类的引用:Derived d; Base &b=d;
// 派生类的对象的地址可以赋给指向基类的指针:Derived d; Base *b; b=&d;
// 因为都是赋给了基类的对象,则只能调用基类的成员函数
// !!!不能将基类的赋给派生类,因为基类的数据成员的构造不够给派生类构造的
Fraction f1(1,2);
Fraction f2(5,6);
f1+=f2;
f1++;
++f1;
cout <<f1;
cout <<f2;
return 0;
}