java基础改学C++(七)类的进一步学习

 一、构造方法 

观察:

class  A{ 

    float   x,y; 

public:

    //构造1:构造函数可以指定参数的缺省值

    A(float a,float b=1){ x=a;  y=b;  }

    //构造2: 无参

    A() {    x=0y=0;  }

    void  Print(void) {cout<<x<<'\t'<<y<<endl;  }     

};

 

int main(void){ 

    A  a1, a2, a3(3.07.0);

    a1.Print();

    a2.Print();

    a3.Print();

 

1、因为构造2的存在,构造1不能给俩参数都有默认值; 

2、这个写法是错的:  A(float a=1,float b){ x=a;   y=b;  } 第一个参数不能有默认值(规定)

3、全局对象,main函数执行之前调用构造函数

4、域不赋默认值 则是随机值,java是0或者false···

 

读个程序:

 

发现,两次调用f();只有一个静态A存在,不是覆盖上的,而是根本没调用第二次构造.和java一样,

一个方法不论被调几次,其内部的静态变量都是初始化1次,并在全局实例析构之前析构

 

再说一遍。。。new 运算符:返回地址  new运算符产生的动态对象,在不再使用这个对象时,必须用delete运算符来释放对象所占用的存储空间

 

demo:

 

class A{ 

public

    int x,y;

    //this指针之前没说,就是java的this

    A(int x,int y){this->x = x;this->y = y;}

   

    void printx();

    //一种初始化方法:

    A(int a,int b,int c):x(a),y(b+c){

        //当需要初始化的数据成员较多时,这种方式更显其优越性.

    }

    //可以在这声明一个函数头,体在下面

    A();

 

    //析构函数:函数名与类名相同,前面加上字符 不能有参数、返回值,不指定函数类型,和构造方法一样 也 有默认的析构函数

    //一个类中,只能定义一个析构函数,析构函数不允许重载,回收对象时由系统自动调用

    ~A(){

  cout<<"a instance deinit";//方法体可以写类外,像构造方法一样

}

 

(一般地,)调用析构函数的次序正好与调用构造函数的次序相反。

};

 

A::A(){

    cout<<"NO para"<<endl;

}

 

 

void A::printx(){

    cout<<x<<endl;

}

 

int main(){

    

    A*a;

    a = newA(10,10);

    

    A a2(10,10,10);

    A*b = & a2;

    

    a->printx();

    b->printx();

    

    delete a;

 

//    用new的必须delete,不new的不能delete

//    直接定义的变量是定义在栈里,随着函数的弹栈而释放

//    new出的东西定义在堆里,需要手动释放,系统不能回收new分配的动态存储空间

 

//引用变量,下面的 a45:

    A & a45 = a2;

//    注意:指针用->,引用用 .

    a45.printx();

//C++与java相比,多了个指针,引用也是有的。声明格式: className & varietyName = instance

}

再看一个demo学习:

 

class Str{

    char *Sp;   int Length;

public

    Str(char *string){

        if(string){

            Length=strlen(string);

            Sp=newchar[Length+1]; //在构造函数中将成员数据指针指向动态开辟的内存

            strcpy(Sp,string);   //用初值为开辟的内存赋值

        }else

            Sp=0;

    }

    

    void Show(){

        cout<<Sp<<endl;

    }

    

    ~Str(){

        if(Sp)

            delete []Sp; //析构函数,当释放对象时收回用new开辟的空间

    }

};

 

   对象如果用new运算符开辟了空间,则在类中应该定义一个析构函数,并在析构函数中使用delete删除由new分配的内存空间

 

int main(){

    Str s1("Study C++");

    s1.Show();

}

 

下面这个demo,可以不看

class A{

public:

    int x,y;

    A(int x,int y):x(x),y(y){

        cout<<"an A instance init "<< endl;

    }

    ~A(){

        cout<<"an instance deinit"<<endl;

    } 

    void printx();  

}; 

void A::printx(){

    cout<<x<<endl;

}

 

class B{ 

public    

    int x,y; 

    B(int x,int y):x(x),y(y){

        cout<<2<<"a B instance init"<<endl;

    }

    ~B(){

        cout<<"an instance deinit"<<endl;

    } 

    void printx();     

}; 

void B::printx(){

    cout<<x<<endl;

}

 

int main(){     

    A*a =new A(10,20); 

    delete a; 

    a->printx();

    ((B*)a)->printx();

自己跑起来看看,打印: 

an A instance init 

an instance deinit

10

10 

1 为什么打印的是10?

原理要从堆内存的实现讲起,从堆上动态申请的内存,在 delete 后,只是将内存块重新添加到当前进程的内存块描述空闲块链表中,内存块内容并不会清空,除非别的线程申请了这个块写入了其他内容,所以10保持不变。

2 为什么 delete 后还能访问,甚至转为 B* 也能访问?

实际上,代码编译后根本就没有类、结构体这些概念,a->printx() 实际上的代码变为:a 处地址,偏移0后,取出地址上的值,打印。打印 y 的话就是 a 偏移 4 字节处,取值。程序根本不知道类这些东西,只是给程序员看的。

 

关于 C++ 中的面向对象

封装和 java 差不多

继承:C++ 支持继承多个类,但是很少会继承多个类,因为基本等于作死,项目大了之后,多继承问题非常多,不如用接口、协议。

多态:一个类的某个成员函数,声明时 前面加上 virtual,后面 = 0,不用写函数实现,子类实现后会自动动态绑定。和 java 多态思想差不多,不多说。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值