C++学习

  • 三、静态成员与友元
    • 1、常量(C++和C语言一样使用const)
      • 例9、常成员函数以及构造函数传参特点
    • 2、静态成员(属于类不属于对象)
      • 例10、无对象情况访问类成员
    • 3、友元(破坏封装)
      • 例11-1、数组末尾追加数据(回顾)
      • 例11-2、倒序(变成从后往前,不是排序)
      • 例11-3、友元类成员(类B的成员成为类A的友元然后类B的成员就可以访问A的私有成员)

三、静态成员与友元

1、常量(C++和C语言一样使用const)

class A{public:A():x(100){}const int x;//常数据成员void func() const;//常成员函数const A a;//常对象
}

例9、常成员函数以及构造函数传参特点

#include <stdio.h>class A{public:A(int data = 0,int a = 1):b(data){//初始化表写法//一般情况所传参数data赋值给b是在{}里写b=data; 但这里b是常量(const int b)所以只能写成:b(data),为了方便于是就统一写成:b(data)这种初始化表写法。this->a = a;//this修饰的a是下面的私有成员int a,使用this是为区分开传参的aprintf("AAAAAAAAA\n");}~A(){printf("~~~~~~~~~\n");}void show(void) const{printf("a = %d\n", a);printf("b = %d\n", b);}private:int a;const int b;
};int main()
{A x(6);x.show();A y(7);y.show();A z;z.show();
}

结果:

@ubuntu:/mnt/hgfs/ub2/class$ g++ const.cpp
@ubuntu:/mnt/hgfs/ub2/class$ ./a.out
AAAAAAAAA
a = 1
b = 6
AAAAAAAAA
a = 1
b = 7
AAAAAAAAA
a = 1
b = 0
~~~~~~~~~
~~~~~~~~~
~~~~~~~~~
@ubuntu:/mnt/hgfs/ub2/class$

根据结果情况发现,a值一直是默认值1,这是因为A x(6);的6是传给data,然后再赋值给b,最后打印出b。构造函数传参是有先后的,data在前所以参数赋给data。

2、静态成员(属于类不属于对象)

static int x;
static const int x = 10;
static int A::x = 10;//类外
static void func();
A::func();//类外调用

例10、无对象情况访问类成员

#include <stdio.h>class A{public:void func(void){printf("xxxxxxxxx\n");}
};int main()
{A a;a.func();
}

上边展示的是一般情况的函数使用:先创建个对象a,然后再由a去访问函数func()。

然而有时候想不创建对象就访问类成员函数,于是可以写成:

A::func();

于是有:

#include <stdio.h>class A{public:void func(void){printf("xxxxxxxxx\n");}
};int main()
{A a;a.func();A::func();
}

结果报错:

@ubuntu:/mnt/hgfs/ub2/class$ g++ static_1.cpp
static_1.cpp: In function ‘int main()’:
static_1.cpp:15:10: error: cannot call member function ‘void A::func()’ without objectA::func();^
@ubuntu:/mnt/hgfs/ub2/class$

错误是因为普通成员函数是需要先创建对象然后根据对象去进行类成员函数访问,能无对象情况访问的是静态成员函数。总的来讲,普通成员函数拒绝单身狗(所以静态就是香)。

改成静态成员函数后如下:

#include <stdio.h>class A{public:static void func(void){printf("xxxxxxxxx\n");}
};int main()
{A a;a.func();A::func();
}

结果:

@ubuntu:/mnt/hgfs/ub2/class$ g++ static_1.cpp
@ubuntu:/mnt/hgfs/ub2/class$./a.out
xxxxxxxxx
xxxxxxxxx
@ubuntu:/mnt/hgfs/ub2/class$

对于成员函数是这样,对于其它数据类型成员亦是如此,比如static int data:

#include <stdio.h>class A{public:static void func(void){printf("xxxxxxxxx\n");}static int data;
};int A::data = 0;//静态成员需要初始化(在类外)int main()
{A a;a.func();A::func();
//普通情况A x;x.data = 6;printf("x.data = %d\n", x.data);//无对象情况A::data = 7;printf("A::data = %d\n", x.data);
}

结果:

@ubuntu:/mnt/hgfs/ub2/class$ g++ static_2.cpp
@ubuntu:/mnt/hgfs/ub2/class$./a.out
xxxxxxxxx
xxxxxxxxx
x.data = 6
A::data = 7
@ubuntu:/mnt/hgfs/ub2/class$

3、友元(破坏封装)

一开始,我们是为了安全性而捆绑封装在一起,但后来发现有些情况下还是要对封装里的成员进行针对性的操作改动,于是就需要友元,让本来私有的可以特定的情况下使用。

friend class B;//友元类
friend void func();//友元函数
friend void B::func();//友元成员函数

在讲友元之前,先回顾下之前的一个案例:

例11-1、数组末尾追加数据(回顾)

arr.h

#ifndef _ARR_
#define _ARR_class ARR{
public:ARR():tail(0){}void addtail(int data);void show(void);private:int data[100];int tail;
};#endif

arr.cpp

#include "arr.h"
#include <stdio.h>void ARR::addtail(int data)
{this->data[tail++] = data;
}void ARR::show(void)
{int i = 0;for(;i<tail; i++)printf("%d, ", data[i]);printf("\n");
}

main.cpp

#include "arr.h"int main()
{ARR arr;arr.addtail(1);arr.addtail(2);arr.addtail(5);arr.addtail(8);arr.addtail(0);arr.show();}

结果:

@ubuntu:/mnt/hgfs/ub2/ARR4$ ls
arr.cpp  arr.h  main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR4$ g++ *.cpp
@ubuntu:/mnt/hgfs/ub2/ARR4$ ./a.out 1, 2, 5, 8, 0,
@ubuntu:/mnt/hgfs/ub2/ARR4$

现在想对以上的数据进行倒序(变成08521)。于是尝试如下:

main.c修改成

#include "arr.h"
void rev(ARR &arr)
{int i = 0;for(;i<arr.tail/2;i++){int tem = arr.data[i];arr.data[i] = arr.data[tail-i-1];arr.data[arr.tail-i-1] = tem;}
}int main()
{ARR arr;arr.addtail(1);arr.addtail(2);arr.addtail(5);arr.addtail(8);arr.addtail(0);arr.show();rev(arr);arr.show();
}

结果报错:

@ubuntu:/mnt/hgfs/ub2/ARR4$ ls
arr.cpp  arr.h  main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR4$ g++ *.cpp
In file included from main.cpp:1:0:
arr.h: In function ‘void rev(ARR&)’:
arr.h:15:6: error: ‘int ARR::tail’ is privateint tail;^
main.cpp:6:16: error: within this contextfor(;i<arr.tail/2;i++)^
In file included from main.cpp:1:0:
arr.h:14:14: error: ‘int ARR::data [100]’ is privateint data[100];^
main.cpp:8:23: error: within this contextint tem = arr.data[i];^
In file included from main.cpp:1:0:
arr.h:14:14: error: ‘int ARR::data [100]’ is privateint data[100];^
main.cpp:9:13: error: within this contextarr.data[i] = arr.data[arr.tail-i-1];^
In file included from main.cpp:1:0:
arr.h:14:14: error: ‘int ARR::data [100]’ is privateint data[100];^
main.cpp:9:27: error: within this contextarr.data[i] = arr.data[arr.tail-i-1];^
In file included from main.cpp:1:0:
arr.h:15:6: error: ‘int ARR::tail’ is privateint tail;^
main.cpp:9:36: error: within this contextarr.data[i] = arr.data[arr.tail-i-1];^
In file included from main.cpp:1:0:
arr.h:14:14: error: ‘int ARR::data [100]’ is privateint data[100];^
main.cpp:10:13: error: within this contextarr.data[arr.tail-i-1] = tem;^
In file included from main.cpp:1:0:
arr.h:15:6: error: ‘int ARR::tail’ is privateint tail;^
main.cpp:10:22: error: within this contextarr.data[arr.tail-i-1] = tem;^
@ubuntu:/mnt/hgfs/ub2/ARR4$

错误信息里有:

arr.h:15:6: error: ‘int ARR::tail’ is private
arr.h:14:14: error: ‘int ARR::data [100]’ is private

说明越界去访问私有成员时被拒绝了。如果不想这种情况的访问被拒绝,就需要在类里边把函数申请为友元。(当然,也可以把这个函数归到类里边作为静态成员函数然后通过类去调用)

例11-2、倒序(变成从后往前,不是排序)

arr.h

#ifndef _ARR_
#define _ARR_class ARR{
public:ARR():tail(0){}void addtail(int data);void show(void);friend void rev(ARR &arr);//把rev函数标记为友元private:int data[100];int tail;
};#endif

arr.cpp

#include "arr.h"
#include <stdio.h>void ARR::addtail(int data)
{this->data[tail++] = data;
}void ARR::show(void)
{int i = 0;for(;i<tail; i++)printf("%d, ", data[i]);printf("\n");
}

main.cpp

#include "arr.h"void rev(ARR &arr)
{int i = 0;for(;i<arr.tail/2;i++){int tem = arr.data[i];arr.data[i] = arr.data[arr.tail-i-1];arr.data[arr.tail-i-1] = tem;}
}int main()
{ARR arr;arr.addtail(1);arr.addtail(2);arr.addtail(5);arr.addtail(8);arr.addtail(0);arr.show();rev(arr);arr.show(); }

结果:

@ubuntu:/mnt/hgfs/ub2/ARR5$ ls
arr.cpp  arr.h  main.cpp
@ubuntu:/mnt/hgfs/ub2/ARR5$ g++ *.cpp
@ubuntu:/mnt/hgfs/ub2/ARR5$ ./a.out
1, 2, 5, 8, 0,
0, 8, 5, 2, 1,
@ubuntu:/mnt/hgfs/ub2/ARR5$

关键字friend标记后就可以进行私有成员访问了。

例11-3、友元类成员(类B的成员成为类A的友元然后类B的成员就可以访问A的私有成员)

首先类A创建一个对象x去访问私有成员y(A x; x.y),然后在类B里面创建个成员函数printfA()打印类A的对象x的私有成员y。于是,类B就可以创建个对象b,然后通过其成员函数去实现类A私有成员y的打印(b.printfA(a);)。 一般情况下只是其某成员比如void printfA(A &x) 需要友元化,其它的类B的成员不需要,所以把整个类B申请为友元不合适。

#include <stdio.h>class A;//这里的存在要引起注意,因为我刻意把案例变得类A中有类B友元处理,类B中成员函数用到类A。
//这种你中有我我中有你就需要这样的重复标识。class B{
public:void printfA(A &x);
};class A{
public:A(){y = 100;}// friend class B;//这句是直接一刀切把整个类友元化friend void B::printfA(A &x);//只是针对类B中的一个成员函数友元化
private:int y;
};void B::printfA(A &x)
{printf("%d\n", x.y);
}int main()
{A a;
//  printf("%d\n", a.x);B b;b.printfA(a);
}

结果:

@ubuntu:/mnt/hgfs/ub2$ g++ friend.cpp
@ubuntu:/mnt/hgfs/ub2$ ./a.out
100
@ubuntu:/mnt/hgfs/ub2$

C++之3|静态成员与友元相关推荐

  1. 实验八 静态成员与友元函数

    实验八 静态成员与友元函数 A. 距离计算(友元函数) 题目描述 输入 输出 输入样例 输出样例 参考代码 B. 银行账户(静态成员与友元函数) 题目描述 输入 输出 输入样例 输出样例 参考代码 C ...

  2. 6 静态成员与友元【C++】

    6- 判断题 1-1 T 静态数据成员不能在类中初始化,使用时需要在类体外声明. 1-2 F 静态成员变量的访问控制权限没有意义,静态成员变量均作为公有成员使用. 1-3 T 友元函数不是类的成员函数 ...

  3. C++ 类与对象_类的其他成员(常成员,静态成员,友元)

    系列文章目录 重新复习c++,所以把书中的重点内容整理成博客,尽量简洁,易懂. C++ 类与对象_类和对象的定义与访问 (定义类和对象,访问对象成员,this指针) C++ 类与对象_构造函数和析构函 ...

  4. 银行账户(静态成员与友元函数)

    题目描述 银行账户类的基本描述如下: 要求如下: 实现该银行账户类 为账户类Account增加一个友元函数,实现账户结息,要求输出结息后的余额(结息余额=账户余额+账户余额*利率).友元函数声明形式为 ...

  5. 静态成员及友元(小题)

    判断题: 1-1 静态成员用以解决同一个类的不同对象之间成员,包括数据成员和函数成员的共享问题.( T ) 1-4 静态成员变量的访问控制权限没有意义,静态成员变量均作为公有成员使用.( F ) 1- ...

  6. 静态成员,友元函数,友元类

  7. c语言类静态数据成员函数,鸡啄米:C++编程入门系列之二十一(C++程序设计必知:类的静态成员)...

    鸡啄米在上一讲数据和函数中讲到,函数之间共享数据也就是此函数访问彼函数的数据主要是通过局部变量.全局变量.类的数据成员.类的静态成员及友元实现的,前三个已经讲过了,这一讲鸡啄米来讲讲静态成员.静态成员 ...

  8. 分享一套C++入门基础视频

    本课程从C++起步.用户无需不论什么计算机基础,仅仅须要懂的主要的电脑操作,既可学习本课程.本课程适合在校大学生,在职人员等,通过本课程的学习,学员可掌握C++\MFC\VC++server端.网络编 ...

  9. C++语言类的详解和示例

    超女选秀的例子我们玩了很久,为了教学的需要,暂时离开美眉们,我将采用实际项目开发的例子. 在C语言基础知识中已学习过文件操作,在实际开发中,我会把文件操作封装成一个类,类的声明如下: 类的声明和成员函 ...

最新文章

  1. MSLicensing​中断远程桌面连接
  2. 费曼:所有科学知识都是不确定的
  3. Simulink仿真---PMSM滞环电流控制仿真模型学习
  4. [TYVJ] P1016 装箱问题
  5. 智能合约WASM语言 (1)概述
  6. IDOC generation debug for One Order
  7. 编译源码 JAVA out of memory
  8. tennylvHTML5实现屏幕手势解锁(转载)
  9. java语言实现一个长度为n_Java语言实现求解一元n次多项式的方法示例[Java代码]...
  10. callablestatement存储过程
  11. python-flask-uwsgi体验
  12. html中设置边框形状为齿状,在CSS中制作锯齿状的三角形边框
  13. java时间转化类,一小时前,刚刚一个月前
  14. [转载] python选择排序二元选择_选择排序:简单选择排序(Simple Selection Sort)
  15. 十、K8s 其他控制器(DS、RC、RS、STS)
  16. 浏览器野史 UserAgent列传
  17. 房东房源管理小程序开发功能
  18. 网站如何统计访问人数?51LA如何安装使用?
  19. 小车PWM调速-串口控制
  20. 蓝桥杯精选赛题系列——统计数字

热门文章

  1. Opencv基于windows平台在vs2013下的安装配置
  2. Color Drawable
  3. OpenCV在Android上踩过的坑
  4. 【交通标志识别】基于BP神经网络实现交通标志识别系统(含语音报警)附matlab代码
  5. OkHttp原理解析
  6. docker-compose 安装部署BSC
  7. 飞机大战——有图片,有声音
  8. Mac下配置tomcat 报错Cannot run program “/Users/xxxxxxx/Library/Tomcat/bin/catalina.sh“ 解决办法
  9. node爬虫puppeteer使用
  10. 原生Python实现网站爬虫