大一下期末C++复习,我不熟的

1.复制构造函数:

eg:
class abc 
{
public:
    abc(int z,int c) 
    {
        x = z; y = c;
    }
    abc(abc const &);//复制构造函数
private:
    int x; int y;

};
abc::abc(abc const &p) 
{
    x = p.x;
    y = p.y;
}
 void abc::out() {
     cout << "x=" << x << ",y=" << y << endl;
}
int main() 
{    abc a(1,2);//建立第一个对象
abc b = a;//调用复制构造函数
abc c(b);//调用复制构造函数
}

2.浅复制和深复制:

若类中没有指针类型,那系统自带的浅复制足够。若是有指针类型,则浅复制复制的是变量的地址,会导致在最后delete的时候释放多次,程序崩溃,因此需要用户自定义一个深复制来防止这一情况的发生。

深复制为:创建一个新的变量,将原变量的值赋值到该变量上,然后再将新的对象里的指针变量指向该变量,导致有两个地址,因此不会崩溃。

eg://意思一致。

int i = 1;
    int *p = &i;
    cout << "&p=" << p << endl;
    int x = *p;
    cout << "x=" << x << endl;
    int *y = &x;
    cout << "&y=" << y << endl;

3.静态函数与静态成员:

静态成员要在类内声明,类外定义。而静态函数里面的成员只能有静态成员,因此静态成员和静态函数是类内不同对象通用的,因此全是静态成员才不会导致可能出现的错误,并且静态函数可以类内定义。

修改办法:mutable 类型 成员变量    eg:mutable int a;

友元:

可以访问所有成员,包括protected,private,public,并且友元是单向的。分为友元类和友元函数,无非就是在一个类中的public里面声明的时候在最前面加一个friend。

eg:

友元类://在定义两个类的时候顺序无所谓,可以让处在上面的友元下面的。

class abc 
{
public:
    
private:
    
    abcd g;
    int x=g.a; int y;
};
class abcd {
    friend class abc;
private:
    int a = 1;

};

友元函数

class abcd {
    friend void acm();
   
private:
    int a = 1;

};
void acm() {
    abcd h;
    cout << h.a << endl;
}

注意:不可以在另一个类中声明该类中的函数friend另一个类,要想使该类的函数可使用另一个类的private成员,必须friend 类。

4.运算符重载:

【1】:成员函数重载:

注意:++和--这种有分为前置和后置,因此参数表内如果在最后加了个int,则为后置。

eg:void operator++(int);//++为自增,不需要参数,因此直接来个int。需要参数的话直接在括号内的最后加个int即可。eg:(int x,int)//(参数,参数,...,int)

定义格式:类型 类名::operator op(参数表);//类型:返回类型。op:运算符

{

//操作

}

声明格式:类型  operator op(参数表);

【2】:用成员或友元函数重载运算符:

注意:有些会加个&。eg:abc::abc &operator++();返回类型不会void,为类的话,为return *this;//this是个指针,表明指向该对象。我觉得&是为了保证改的确实是那个对象的那个参数,地址那种感觉。

成员函数:

一元运算:Object.operator op();二元运算:Object.operator op(Object.a);

友元函数:

一元运算:operator op(ObjectB b);//一个类型的对象

二元运算:Object.operator op(ObjectB a,ObjectB b);

注意:友元函数不可以重载 = 和 () 和 [ ] 和 -> 。

重载赋值运算符:

//赋值运算符用于对象数据的复制,只能用成员函数重载,且不能被继承。

格式:类名 &类名::operator=(类名);                          一定要用&

eg:Name &Name::operator=(Name);

重载运算符[ ]和():

//只能用成员函数重载。

(1):重载下标 [ ] 运算符://为二元运算符        

eg:声明:int &X::operator[ ](int);//X为一个类。               一定要用&

       调用:x.operator[ ](k);//x为X类的对象。

(2):重载函数调用运算符()://为二元运算符

eg:声明:int A::operator()(int,int);//A为类。

       调用:a(x,y)//a为类A的对象。被解释为:a.operator()(x,y);

重载流插入<< 和 流提取>>运算符:

(1):重载流插入<<://cout        一定要用&

//第一个ostream为返回类型 ,()里面的&是为了确保一定改的是这个对象。

//const 是为了保证引用的对象不会被改变。 Vector为数据类型。

声明:ostream &operator<<(ostream &output,const Vector &);

定义:ostream &operator<<(ostream &output,const Vector &A)

{

for(int i=0;i<A.len;i++){output<<A.v[i]<<"i"<<endl;}

return output;

}

(2):重载流提取>>://cin       一定要用&

//第一个istream为返回类型 ,()里面的&是为了确保一定改的是这个对象。

//const 是为了保证引用的对象不会被改变。 Vector为数据类型。

声明:istream &operator>>(istream &iutput,const Vector &);

定义:istream &operator>>(istream &iutput,const Vector &A)

{

for(int i=0;i<A.len;i++){iutput>>A.v[i]<<"i"<<endl;}

return iutput;

}

5.类类型转换:

不过就是前面的运算符重载里面的参数类型不同,然后通过内部的运算进行转化而已。

6.继承://C++可以继承多个类,Java只能继承一个父类,但是可以有多个接口

class A {
public:
    void abc() {
        cout << " A" << endl;
    }
protected:
    int x = 1;
};
class B :public A{
public:
    void abc() {
        cout << " B" << endl;
    }
protected:
    int x = 1;
};

int main() {
    A a;//A的对象a
    B b;//B的对象b
    a.abc();//调用a的abc函数
    b.abc();//基类的重名函数会被屏蔽,所以调用的是b的abc函数
    b.A::abc();//这就是在b中调用A的abc函数的方法
}

初始化顺序和结束顺序:                           

初始化: 顺序                                                            

1.基类的构造 2.子类的构造                                           

结束顺序:                                                                     

3.子类的析构 4.基类的析构 

                         

7.虚继承:

就是共用一个父类。

定义方式:class A :virtual public B;//A类虚继承B

                  class C :virtual public B;//C类虚继承B

A类和C类公用B类的成员。

8.多态,也包括了虚函数:

静态多态:函数地址早绑定,编译的时候就已经确定了函数地址。

动态多态:函数地址晚绑定,运行的时候才确定函数地址。父类的指针或引用指向子类对象。说明了下面为什么要用&。//指针都是四个字节。

以下为动态多态:

正常情况下:

class A {
public:
    void speak() { cout << "A is speaking" << endl; }
};

class B :public A{
public:
    void speak() { cout << "B is speaking" << endl; }
};
void ALLspeak(A &a)  //这个&是关键,如果没有&,那调用结果还是A的speak()。

{
    a.speak();
}
int main() {
    B b;
    ALLspeak(b);
}

由于C++的特性,该ALLspeak()可以调用,但是调用的话因为类型为A,所以输出的是A的speak(),而不是B的speak()。此时我们的函数地址是早绑定的,但此时我们真正的目的是调用子类B的speak(),因此需要使用多态使函数地址晚绑定,以输出B的speak()。

此时的操作为将父类A的speak()变为虚函数

//这样,必须父类和子类的该函数返回类型和名字一致。

virtual void speak()

{ cout << "A is speaking" << endl; }

//此时该函数还是可以直接用调用的,但是若变为纯虚函数,则无法调用,导致该类无法实例化。
eg:

    A a;//A类中含有抽象类。
    a.speak();

此时会根据speak(参数)的参数类型决定调用该对象的speak(),此时为地址晚绑定,在运行使才绑定函数地址。

纯虚函数和抽象类:

因为以上情况的父类的函数压根就不用,所以干脆直接不需要实现该虚函数的功能,因此可以改为纯虚函数:virtual 返回值类型 函数名(参数列表)=0;

eg:virtual void speak()=0;

但是Java的为abstract void speak()即可,不需要等于0。

而有纯虚函数的类就是抽象类

抽象类特点:

(1).无法实例化对象。

(2).子类必须重写该抽象类中的纯虚函数,否则也变成抽象类。

虚析构和纯虚析构://Java没有析构函数,因为它会自动释放。

多态使用的时候,如果子类有指针类型,开辟到堆区,那么释放的时候无法调用子类的析构函数,而导致子类对象内存泄漏。eg:

A *a=new B;//跟Java一样,左父右子。

a ->speak();

delete a;//此时不会释放子类的析构函数,父类构造析构都正常,子类的构造函数也可以调用。

因此需要虚析构和纯虚析构来解决这个问题。

//如果有了纯虚析构,则该类属于抽象类,无法实例化对象,跟纯虚函数一样。

解决办法:虚析构

把父类A的析构函数改为虚析构即可。

eg:virtual ~A(){};

//虚析构也会被调用,纯虚析构也一样,因为可能父类中也有成员变量在堆区。

而纯虚析构为:virtual ~A()=0;

在类内要virtual ~A()=0;//但是可以在类外定义它,防止父类内存泄漏。

eg:A::~A(){ };

9.模板: (类模板和函数模板)

//template <class T1,class T2,......>要紧跟下面的类或者函数,不能分开。

目的:制造一些东西可以通用。

模板说明格式:template<class T1,class T2,.......>//T1,T2为类型。

函数模板://可以重载

eg:定义

template<class T>

T max(T a,T b){

return a>b?a:b;

}

调用:

int a=1,b=2;

max(a,b);

类模板:

eg:定义

template<class T>

class abc{

public:

T MAX()

{

return x>y?x:y;

}

protected:

T x,y;

};

写文件读文件之类的:

/*
文件打开方式:
ios::in     为读文件而打开文件
ios::out    为写文件而打开文件
ios::ate    初始位置:文件尾
ios::app    追加方式写文件
ios::trunc  如果文件存在先删除,再创建
ios::binary 二进制方式
打开方式可以配合使用。eg:  ios::binary|ios::out
                      用 |
fstream A;
    A.open("测试文件.txt", ios::out);
    A << "石家庄" << endl;
    A << "      一加一等于二" << endl;
    A.close();
    fstream B;
    B.open("测试文件.txt", ios::in);
    char g[1024] = { 0 };
    /*while (B>>g)
    {
        cout << g << endl;
    }
while (B.getline(g, sizeof(g)))
{
    cout << g << endl;
};
B.close();
*/

一些好玩的小函数://现在使用的是中文标点符号,需要到时改成英文标点符号。

system(“pause”);//按任意键继续

system(“cls”);//自动清空cmd显示器

abort();//退出程序

return 0;//直接结束全部程序

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值