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语言的高效而诞生的
  • 友元直接破坏了面向对象的封装性
  • 友元在实际产品中的高效是得不偿失的
  • 友元在现代软件工程中已经逐渐被遗弃

注意事项:

  • 友元关系不具备传递性
  • 类的友元可以是其它类的成员函数
  • 类的友元可以是某个完整的类
    1. 所有的成员函数都是友元

示例二:

#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++中通过函数名和函数参数确定函数调用
  • 无法直接通过函数名得到重载函数的入口地址
  • 函数重载必然发生在同一个作用域中

类中的重载——类中的成员函数可以进行重载:

  • 构造函数的重载
  • 普通成员函数的重载
  • 静态成员函数的重载

问题:

全局函数,普通成员函数以及静态成员函数之间是否可以构成重载?

万变不离其宗:

  1. 重载函数的本质为多个不同的函数
  2. 函数名参数列表是唯一的标识
  3. 函数重载必须发生在同一个作用域中

示例:

#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):友元与类中的函数重载的更多相关文章

  1. C++类中的函数重载

    1,本课程最初阶段就学习了函数重载,但是那时研究目标仅限于全局函数,到目前 为止我们学习了三种函数: 1,全局函数: 2,普通成员函数: 3,静态成员函数: 这三种不同类型的函数之间是否可以构成重载, ...

  2. Effective Java 第三版——16.在公共类中使用访问方法而不是公共属性

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  3. C++走向远洋——49(项目一2、复数类中的运算符重载、类的友元函数)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  4. 类中成员函数与数据成员private/pubic/protected

    类中成员函数与数据成员private/pubic/protected

  5. cocos2dx lua 绑定之一:自动绑定自定义类中的函数

    cococs2dx 3.13.1 + vs2013 + win10 1.首先定义C++类Student 在cocos2d-x\cocos文件夹下新建一个user_define的文件夹放置两个文件. 注 ...

  6. 【java&c++】父子类中同名函数的覆盖问题

    java和c++两门语言对于父子类中同名函数具有不同的处理方式. 先上两段代码: C++: class Basic { public: void test(string i){ cout <&l ...

  7. string类中getline函数的应用

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  8. C++走向远洋——50(Time类中的运算符重载、一目,二目比较运算符、二目赋值运算符、二目加减法运算符)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  9. C++走向远洋——48(项目一1、复数类中的运算符重载、类的成员函数)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

随机推荐

  1. day6 角点检测

    1.Harris角点检测 # coding=utf-8 import cv2 import numpy as np filename = 'pic5.png' #1.读入一个灰度图像 img = cv ...

  2. Docker入门篇(二)之docker的单主机网络

    Docker 安装时会自动在host上创建三个网络,我们可用 docker network ls命令查看: [root@localhost ~]# docker network ls NETWORK ...

  3. Java EE JavaBean组件

    一.简介 JavaBean组件是一些可移植.可重用并可组装到应用程序中的Java类,类必须是具体的和公共的. 符合下列设计规则的任何Java类均是以JavaBean: 1.对数据类型“protype” ...

  4. 人脸检测及识别python实现系列(6)——终篇:从实时视频流识别出“我”

    人脸检测及识别python实现系列(6)——终篇:从实时视频流识别出“我” 终于到了最后一步,激动时刻就要来临了,先平复一下心情,把剩下的代码加上,首先是为Model类增加一个预测函数: #识别人脸 ...

  5. js页面跳转,url带url参数解决方案

    今天,在做一个项目的时候,向后端发送了一个Ajax请求,后端返回了一个字符串,告诉我未登录.那么我需要跳转到登录页面,同时告诉登录页面,登录成功后,需要跳回的url.也就是标题所说,url中的一个参数 ...

  6. Scrum立会报告+燃尽图(Beta阶段第二周第一次)

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2409 项目地址:https://coding.net/u/wuyy694 ...

  7. C++:默认初始化

    一.什么是默认初始化 默认初始化,顾名思义,即为在定义变量时如果没有为其指定初始化值,则该变量会被C++编译器赋予默认的值.而变量被赋予的默认值到底是什么,则取决于变量的数据类型和变量的定义位置. 二 ...

  8. iframe高度自适应的6个方法

    原文链接:http://caibaojian.com/iframe-adjust-content-height.html JS自适应高度,其实就是设置iframe的高度,使其等于内嵌网页的高度,从而看 ...

  9. Transparent Flow Migration for NFV

    Transparent Flow Migration for NFV 摘要 因为SDN提供的灵活性,NF之间存在着流量的迁入和迁出问题.而且NF也要根据相关的状态信息处理数据包,所以流量迁移必须满足以 ...

  10. MiniOS系统

    实验一  命令解释程序的编写 一.目的和要求 1. 实验目的 (1)掌握命令解释程序的原理: (2)*掌握简单的DOS调用方法: (3)掌握C语言编程初步. 2.实验要求 编写类似于DOS,UNIX的 ...