C++中类的真身和对象的构造(一)

2022-03-21 09:25:28 浏览数 (1)

前言

在上一篇文章里面我们讲解了类的封装,网友们看完后,感觉跟c语言差不多,就是多了两个关键字public和private,其它和c语言的写法没啥差别。其实这里还有很多c 的知识点没有讲解到,暂时是分享面向对象语言的重点(后期会补上那些基础知识点);其实面向对象的思想也是可以用c语言写出来的(虽然说c语言是一门面向过程的语言,但是c语言真的很博大精深!)。——每天进步一点点,日积月累你也是专家。

 类的真身

1、类的关键字:

     在类的封装文章里面,我们使用了关键字"struct  name"来表示创建了一个类名,但是其实在c 里面,创建类的关键字不是strcut,而是我们的“class”;这里我们发现这两个字都可以用来创建一个类名,那他们肯定是有区别的吧;的确,这两个关键字有区别(在实际写c 的程序还是用class来创建类名;使用struct关键字来创建类名的话,不是不可以,主要是写法很像c语言里面的结构体,现在毕竟在学习c ,所以还是多用class,同时这也就能解释为啥c语言能够写出面向对象的思想了):

  • 在使用struct定义类时,所有成员的默认访问级别为public(也就是说,外部的对象可以调用和访问类里面的东西)。
代码语言:javascript复制
 struct A
 {
        //default to public
        int i;
       //default to public
        int get()
        {
           return i;
        }
 }
  • 在使用class定义类时,所有成员的默认访问级别为private(也就是说外部的对象不能调用和访问类里面的东西了)。
代码语言:javascript复制
 struct B
 {
        //default to private
        int i;
       //default to private
        int get()
        {
           return i;
        }
 }

下面我们来看一个实际例子:

代码语言:javascript复制
  #include <iostream>
  using namespace std;
  struct A
  {
      // defualt to public
      int i;
     // defualt to public
     int get()
     {
        return i;
     }
  };

 class B
  {
     // defualt to private
     int i;
     // defualt to private
     int get()
    {
        return i;
    }
  };

 int main()
 {
     A a;
     B b;

    a.i = 4;

    //printf("a.getI() = %dn", a.get());
      cout<<"a.get()="<<a.get()<<endl;

     b.i = 4;

   //  printf("b.getI() = %dn", b.getI());
      cout<<"a.get()=%dn"<<b.get()<<endl;

   return 0;
 }

演示结果:

代码语言:javascript复制
  Error:"int B::i"is private
  Error:"int B::get()"is private

从上面结果我们可以看出使用class来创建类名时,外部就不能访问类里面的东西了,否则就会报错(因为类里面的属性和行为都是私用的,不是公开的)。(上面的例子几乎是用c 里面的知识来写的,其中using namespace std,以及cout这些暂时先在这里不介绍,就先知道cout和c语言里面的printf函数一样,用来打印输出的就行了,这几天之内会介绍的)。

对象的构造

1、不知道读者有没有注意,在上面定义的类中,类里面的属性没有给它初始化,那到底是多少呢,是0还是随机值呢?对于这个问题我们还是通过例子做实验来说话:

代码语言:javascript复制
 #include <iostream>
 using namespace std;
 class Test
  {
    private:
        int i;
        int j;
    public:
        int get1()
        {
            return i;
        }
        int get2()
        {
            return j;
        }
  };

 Test gt;
 int main(void)
 {

     cout<<"gt.i = "<<gt.get1()<<endl;
     cout<<"gt.j = "<<gt.get2()<<endl;

     Test gt2;

    cout<<"gt2.i = "<<gt2.get1()<<endl;
    cout<<"gt2.j = "<<gt2.get2()<<endl;

    Test *p=new Test;

    cout<<"p->i = "<<p->get1()<<endl;
    cout<<"p->j = "<<p->get2()<<endl;

    delete p;

    return 0;
 }

演示结果:

代码语言:javascript复制
gt.i = 0
gt.j = 0
gt2.i = 12129664
gt2.j = 7208832
p->i = 0
p->j = 0

从实验结果我们可以发现以下结论(从程序设计的角度来看,对象只是变量):

  • 在栈创建对象时,对象访问类中的属性初始化时随机值(就比如上面的gt2.i= 12129664,gt2.j=7208832)。
  • 在堆上创建对象时,对象访问类中的属性也是为随机值(这里试验结果虽然是0,但是实际结果不好说;同时这里使用new为指针p 分配了空间,在使用完后,我们要进行释放,这里使用delete关键字;这里类似我们c语言利用malloc函数来分配堆空间,同时使用free释放堆空间)。
  • 在静态存储去创建对象时,对象访问类中的属性初始值为0(就是我们这里gt.i=0,gt.j=0)。

2、其实一般来说对象访问类里面的属性都要有一个初始化,在c 里面有一一个构造函数,就可以解决对象访问类中的属性初值问题,就不用管第一条说的那样(分栈、堆啥的),那我们怎样使用构造函数呢?首先我们要明白构造函数的定义:

  • C 中可以定义与类名相同的特殊成员函数,这个特殊成员函就是构造函数了
  • 构造函数没有任何返回类型的声明。
  • 构造函数在对象定义时自动被调用
代码语言:javascript复制
 #include <iostream>
 using namespace std;
 class Test
  {
    private:
        int i;
        int j;
    public:
           Test()
           {   

              i = 1;
              j = 2;

           }
        int get1()
        {
            return i;
        }
        int get2()
        {
            return j;
        }
  };

 Test gt;
 int main(void)
 {

     cout<<"gt.i = "<<gt.get1()<<endl;
     cout<<"gt.j = "<<gt.get2()<<endl;

     Test gt2;

    cout<<"gt2.i = "<<gt2.get1()<<endl;
    cout<<"gt2.j = "<<gt2.get2()<<endl;

    Test *p=new Test;

    cout<<"p->i = "<<p->get1()<<endl;
    cout<<"p->j = "<<p->get2()<<endl;

    delete p;

    return 0;
 }

演示结果:

代码语言:javascript复制
gt.i = 1
gt.j = 2
gt2.i = 1
gt2.j = 2
p->i = 1
p->j = 2

总结

好了,今天的分享就到这里,晚安!

0 人点赞