C++解析(16):友元与类中的函数重载
0.目录
1.友元的尴尬能力
2.类中的函数重载
3.小结
1.友元的尴尬能力
什么是友元?
- 友元是C++中的一种关系
- 友元关系发生在函数与类之间或者类与类之间
- 友元关系是单项的,不能传递
友元的用法:
- 在类中以friend关键字声明友元
- 类的友元可以是其它类或者具体函数
- 友元不是类的一部分
- 友元不受类中访问级别的限制
- 友元可以直接访问具体类的所有成员
友元的语法——在类中用friend关键字对函数或类进行声明:
示例一:
#include <stdio.h>
#include <math.h>
class Point
{
double x;
double y;
public:
Point(double x, double y)
{
this->x = x;
this->y = y;
}
double getX()
{
return x;
}
double getY()
{
return y;
}
friend double func(Point& p1, Point& p2);
};
double func(Point& p1, Point& p2)
{
double ret = 0;
ret = (p2.y - p1.y) * (p2.y - p1.y) +
(p2.x - p1.x) * (p2.x - p1.x);
ret = sqrt(ret);
return ret;
}
int main()
{
Point p1(1, 2);
Point p2(10, 20);
printf("p1(%f, %f)\n", p1.getX(), p1.getY());
printf("p2(%f, %f)\n", p2.getX(), p2.getY());
printf("|(p1, p2)| = %f\n", func(p1, p2));
return 0;
}
运行结果为:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
p1(1.000000, 2.000000)
p2(10.000000, 20.000000)
|(p1, p2)| = 20.124612
友元的尴尬:
- 友元是为了兼顾C语言的高效而诞生的
- 友元直接破坏了面向对象的封装性
- 友元在实际产品中的高效是得不偿失的
- 友元在现代软件工程中已经逐渐被遗弃
注意事项:
- 友元关系不具备传递性
- 类的友元可以是其它类的成员函数
- 类的友元可以是某个完整的类
- 所有的成员函数都是友元
示例二:
#include <stdio.h>
class ClassC
{
const char* n;
public:
ClassC(const char* n)
{
this->n = n;
}
friend class ClassB;
};
class ClassB
{
const char* n;
public:
ClassB(const char* n)
{
this->n = n;
}
void getClassCName(ClassC& c)
{
printf("c.n = %s\n", c.n);
}
friend class ClassA;
};
class ClassA
{
const char* n;
public:
ClassA(const char* n)
{
this->n = n;
}
void getClassBName(ClassB& b)
{
printf("b.n = %s\n", b.n);
}
/* 友元关系不具备传递性
void getClassCName(ClassC& c)
{
printf("c.n = %s\n", c.n);
}
*/
};
int main()
{
ClassA A("A");
ClassB B("B");
ClassC C("C");
A.getClassBName(B);
B.getClassCName(C);
return 0;
}
运行结果为:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
b.n = B
c.n = C
2.类中的函数重载
函数重载回顾:
- 函数重载的本质为相互独立的不同函数
- C++中通过函数名和函数参数确定函数调用
- 无法直接通过函数名得到重载函数的入口地址
- 函数重载必然发生在同一个作用域中
类中的重载——类中的成员函数可以进行重载:
- 构造函数的重载
- 普通成员函数的重载
- 静态成员函数的重载
问题:
全局函数,普通成员函数以及静态成员函数之间是否可以构成重载?
万变不离其宗:
- 重载函数的本质为多个不同的函数
- 函数名和参数列表是唯一的标识
- 函数重载必须发生在同一个作用域中
示例:
#include <stdio.h>
class Test
{
int i;
public:
Test()
{
printf("Test::Test()\n");
this->i = 0;
}
Test(int i)
{
printf("Test::Test(int i)\n");
this->i = i;
}
Test(const Test& obj)
{
printf("Test(const Test& obj)\n");
this->i = obj.i;
}
static void func()
{
printf("void Test::func()\n");
}
void func(int i)
{
printf("void Test::func(int i), i = %d\n", i);
}
int getI()
{
return i;
}
};
void func()
{
printf("void func()\n");
}
void func(int i)
{
printf("void func(int i), i = %d\n", i);
}
int main()
{
func();
func(1);
printf("\n");
Test t; // Test::Test()
Test t1(1); // Test::Test(int i)
Test t2(t1); // Test(const Test& obj)
printf("\n");
func(); // void func()
Test::func(); // void Test::func()
printf("\n");
func(2); // void func(int i), i = 2;
t1.func(2); // void Test::func(int i), i = 2
t1.func(); // void Test::func()
return 0;
}
运行结果为:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
void func()
void func(int i), i = 1
Test::Test()
Test::Test(int i)
Test(const Test& obj)
void func()
void Test::func()
void func(int i), i = 2
void Test::func(int i), i = 2
void Test::func()
全局函数与类中的成员函数不可以构成重载。
重载的意义:
- 通过函数名对函数功能进行提示
- 通过参数列表对函数用法进行提示
- 扩展系统中已经存在的函数功能
原有的字符串拷贝功能:
#include <stdio.h>
#include <string.h>
int main()
{
const char* s = "Hello World!";
char buf[16] = {0};
strcpy(buf, s);
printf("%s\n", buf);
return 0;
}
但是若是buf的长度不够,就会出错!
因此采用函数重载进行修改:
#include <stdio.h>
#include <string.h>
char* strcpy(char* buf, const char* str, unsigned int n)
{
return strncpy(buf, str, n);
}
int main()
{
const char* s = "Hello World!";
char buf[8] = {0};
//strcpy(buf, s);
strcpy(buf, s, sizeof(buf)-1);
printf("%s\n", buf);
return 0;
}
运行结果为:
[root@bogon Desktop]# g++ test.cpp
[root@bogon Desktop]# ./a.out
Hello W
重载能够扩展系统中已经存在的函数功能!那么重载是否也能够扩展其它更多的功能?(更多内容下节分解......)
3.小结
- 友元是为了兼顾C语言的高效而诞生的
- 友元直接破坏了面向对象的封装性
- 友元关系不具备传递性
- 类的友元可以是其它类的成员函数
- 类的友元可以是某个完整的类
- 类的成员函数之间可以进行重载
- 重载必须发生在同一个作用域中
- 全局函数和成员函数不能构成重载关系
- 重载的意义在于扩展已经存在的功能
C++解析(16):友元与类中的函数重载的更多相关文章
- C++类中的函数重载
1,本课程最初阶段就学习了函数重载,但是那时研究目标仅限于全局函数,到目前 为止我们学习了三种函数: 1,全局函数: 2,普通成员函数: 3,静态成员函数: 这三种不同类型的函数之间是否可以构成重载, ...
- Effective Java 第三版——16.在公共类中使用访问方法而不是公共属性
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- C++走向远洋——49(项目一2、复数类中的运算符重载、类的友元函数)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- 类中成员函数与数据成员private/pubic/protected
类中成员函数与数据成员private/pubic/protected
- cocos2dx lua 绑定之一:自动绑定自定义类中的函数
cococs2dx 3.13.1 + vs2013 + win10 1.首先定义C++类Student 在cocos2d-x\cocos文件夹下新建一个user_define的文件夹放置两个文件. 注 ...
- 【java&c++】父子类中同名函数的覆盖问题
java和c++两门语言对于父子类中同名函数具有不同的处理方式. 先上两段代码: C++: class Basic { public: void test(string i){ cout <&l ...
- string类中getline函数的应用
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- C++走向远洋——50(Time类中的运算符重载、一目,二目比较运算符、二目赋值运算符、二目加减法运算符)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- C++走向远洋——48(项目一1、复数类中的运算符重载、类的成员函数)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
随机推荐
- 验证码示例代码演示——以php为例
运行 · 修改index.php(图片验证码的生成示例) [html] view plain copy initNECaptcha({ captchaId: 'YOUR_CAPTCHA_ID', // ...
- ln in Linux
默认情况(硬连接) ln 目标 连接名称 ll -i 显示文件的inode信息,即文件节点信息 ➜ test1 ll -i 1.txt 27987655 -rw-r--r-- 1 myuser ...
- git clone、git pull和git fetch的用法及区别
声明:码字不易,转载请注明出处,欢迎文章下方讨论交流.Git 常用命令速查表 最近在一个学习小组里学习AI的课程,我们所有的学习资料和homework都放在gitlab上.今天一个小队友从gitlab ...
- Scrapy爬去哪儿~上海一日游门票并存入MongoDB数据库
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZwAAAGGCAYAAABPDDfEAAAgAElEQVR4nOy9C3Rb1Z3/+z1Hkm35mT
- 英特尔® 实感™ 前置摄像头 SR300 和 F200 的比较
原文地址 简介 SR300 是支持 Microsoft Windows 10 操作系统的第二代英特尔® 实感™ 前置摄像头. 与 F200 摄像头型号相似,SR300 使用编码光深技术,在更小范围内创 ...
- 母版页 MasterPage
母版页是一个扩展名为.master的ASP.NET文件,主要是为了应用程序创建统一的用户功能界面和样式. ContentPlaceHolder控件只能在母版页中使用,在平常的web页面使用,会发生解析 ...
- vps搭建个人网盘不二之选—kodexplorer介绍,包含安装步骤
之前给大家介绍过seafile.h5ai等网盘系统,今天给大家介绍下kodexplorer网盘系统.Kodexplorer,也叫芒果云.可道云.kodcloud,总之名字改了不少.但其本身作为一个网盘 ...
- Beta阶段中间产物
空天猎功能说明书:https://git.coding.net/liusx0303/Plane.git 空天猎代码控制:https://coding.net/u/MR__Chen/p/SkyHunte ...
- asp.net登录状态验证
文章:ASP.NET 登录验证 文章:ASP.NET MVC下判断用户登录和授权状态方法 文章:.net学习笔记---HttpHandle与HttpModule 第一篇文章,介绍了 1)早期的Base ...
- 开发环境解决 kafka Failed to send messages after 3 tries
新建了一个kafka集群,在window下写了一个简单的producer做测试,结果遇到了消息发送失败的问题,代码如下: Properties props = new Properties(); pr ...