在上一篇文章里面我们讲解了类的封装,网友们看完后,感觉跟c语言差不多,就是多了两个关键字public和private,其它和c语言的写法没啥差别。其实这里还有很多c 的知识点没有讲解到,暂时是分享面向对象语言的重点(后期会补上那些基础知识点);其实面向对象的思想也是可以用c语言写出来的(虽然说c语言是一门面向过程的语言,但是c语言真的很博大精深!)。——每天进步一点点,日积月累你也是专家。
类的真身
1、类的关键字:
在类的封装文章里面,我们使用了关键字"struct name"来表示创建了一个类名,但是其实在c 里面,创建类的关键字不是strcut,而是我们的“class”;这里我们发现这两个字都可以用来创建一个类名,那他们肯定是有区别的吧;的确,这两个关键字有区别(在实际写c 的程序还是用class来创建类名;使用struct关键字来创建类名的话,不是不可以,主要是写法很像c语言里面的结构体,现在毕竟在学习c ,所以还是多用class,同时这也就能解释为啥c语言能够写出面向对象的思想了):
- 在使用struct定义类时,所有成员的默认访问级别为public(也就是说,外部的对象可以调用和访问类里面的东西)。
struct A
{
//default to public
int i;
//default to public
int get()
{
return i;
}
}
- 在使用class定义类时,所有成员的默认访问级别为private(也就是说外部的对象不能调用和访问类里面的东西了)。
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 中可以定义与类名相同的特殊成员函数,这个特殊成员函就是构造函数了。
- 构造函数没有任何返回类型的声明。
- 构造函数在对象定义时自动被调用。
#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
总结
好了,今天的分享就到这里,晚安!