面向对象学习笔记(避雷篇)
时间还挺快的,当年的 OIer 已经上大学啦!在大学的 C++ 学习中,要求我们掌握两种编程技巧,即面向对象和面向过程。
因为高中时期不管是 CSP 还是 NOIp 的比赛,大家用的基本上都是面向过程的设计思路,因此我开学后就着重开始学习面向对象的方法。
这里对面向对象的概念不做细致的讨论了。总之,复杂的也用不到,现在的水平只能做到 “封装” 这一项。
下面来整理一下最近写代码时候遇到的困难和解决办法。
在类外调用类内的静态函数
大多数时候,我们要指定特定的某一个对象去调用 public
中的函数,但是也有一些情况,不可避免的要直接调用类内 public
中的函数,这时候可以使用静态函数的方法。
class Example
{
static void test()
{
//do something ...
}
};
//在其他函数中
Example::test();
- 原理:
static
关键词表示这是类内公用的一个函数/变量(静态函数/变量),它不属于类内的任意一个对象。因此,可以跳过指定对象的环节直接调用。
在类外调用类内的静态变量
类似上面,我们有一个公共的变量 a
。不管定义了多少个对象,它们都公用这一个变量 a
,相应的,变量 a
也只占对应变量类型的空间大小,不会随对象的增多而占用更多的空间。
在类内的函数中,可以直接调用 a
。
在类外的函数中,可以使用 classname::a
来调用变量 a
。
class Example
{
static int a;
void test1()
{
std::cout << a;
}
};
void test2()
{
std::cout << Example::a;
}
int Example::a;
// 这一句很重要,下面讲为什么
需要注意的是,在类内写出 static int a;
这样的句子不被视为 “定义” 行为,而是 “声明” 行为。因为 a
的 static
属性,导致它不属于任意一个对象,所以在开内存的时候,它不能占用任意一个对象的内存,也不能被构造函数初始化。
所以,需要在类外,再次单独给出一次 a
的 “定义”,分配给它一个内存。如果需要的话,也要单独的初始化它。这样才能正常地调用静态变量 a
。
如果不在类外重新定义 a
的话,编译器会报错 "undefined symbol" 。
在类外强行访问 private 中的元素
尽管这有违面向对象的初衷——保护对象中的元素不能直接从外部访问,但是有时候我们不得不这样做,这就用到了友元关键词 friend
。
关键词 friend
可以授权其他的类或者函数直接访问该类中的 private
或者protect
中的元素。
class Example
{
public:
friend void test1();
private:
int a;
}e;
void test1()
{
std::cout << e.a;
}
//test1() 可以运行,因为 friend 关键词授予了它访问 private 元素的权限
void test2()
{
std::cout << e.a;
}
//test2() 不能运行,报错显示无权访问 private 中的元素
构造函数需要传参
如果使用构造函数初始化的话,那么大概率需要传参,但是参数又大多都是用户输入的,这就会导致无法把对象定义为全局变量(因为不知道参数,定义的时候会因为构造函数中没有参数而报错)。
一种显而易见的解决方法是不要用构造函数初始化,自己另写一个带 static
关键词类型的初始化函数,然后在主函数中调用。
如果自带反骨,一定要用带参数的构造函数初始化,并且还想开全局变量的话,也有办法:使用 std::vector
。因为 vector
容器的初始长度为 0 ,不占用任何内存,所以声明的时候不会调用构造函数,避免了报错。
在主函数中得到数据之后,可以再把数据打包起来然后用构造函数加 pushback()
函数塞到类里面。
class Example
{
public:
Example(const int A[])
{
for(int i = 0 ; i < 3 ; i ++)
a[i] = A[i];
}
private:
int a[3];
};
std::vector < Example > V;
int main()
{
int a[3];
for(int i = 0 ; i < 3 ; i ++)
std::cin >> a[i];
V.push_back( Example(a) );
return 0;
}
构造函数的初始化列表
用初始化列表来写构造函数会让代码更整洁!
class Example
{
public:
Example(int A, int B) : a(A), b(B){}
/*
等价于
Example(int A, int B)
{
a = A;
b = B;
}
*/
private:
int a, b;
};
另外有个顺序问题,详情可以看这篇 blog 。
标签:初始化,调用,函数,避雷,笔记,面向对象,int,Example,构造函数 From: https://www.cnblogs.com/zaza-zt/p/17726090.html