C++继承中的同名覆盖
1,父子间的冲突是由继承带来的,两个类之间存在了继承的关系,必然的会带来一 些问题,本文要讨论的是父子之间成员变量或成员函数的命名问题;
2,思考:
1,子类中是否可以定义父类中的同名成员?
1,可以,本文先编程解决这个问题;
2,这个问题就是同名覆盖问题;
2,如果可以,如何区分?如果不可以,为什么?
3,同名成员变量编程实验:
#include <iostream>
#include <string> using namespace std; class Parent
{
public:
int mi;
}; class Child : public Parent
{
public:
int mi; // 编译结果通过,子类可以定义父类里面的同名变量;
}; int main()
{
Child c; c.mi = ; // mi 究竟是子类自定义的,还是从父类继承得到的? return ;
}
4,父子间的冲突(同名覆盖):
1,子类可以定义父类中的同名成员;
2,子类中的成员将隐藏父类中的同名成员;
1,编译器认为已经从父类中继承得到这个成员了,又自定义了一个同名成员,目的只有一个,就是你想要自己自定义的同名成员、而不想要从父类那里继承得到的同名成员,因此会产生同名覆盖现象;
3,父类中的同名成员依然存在于子类中;
1,隐藏、不是销毁;
4,通过作用域分辨符(::)访问父类中的同名成员;
5,访问父类中的同名成员方式:
1,Child c;
2,c.mi = 100; // 子类中的 mi;
3,c.Parent::mi = 1000; // 父类中的 mi;
6,同名成员变量深度分析编程实验:
#include <iostream>
#include <string> using namespace std; namespace A
{
int g_i = ;
} namespace B
{
int g_i = ; // 同名的全局变量,但是位于两个不同的命名空间;
} class Parent
{
public:
int mi; Parent()
{
cout << "Parent() : " << "&mi = " << &mi << endl;
}
}; class Child : public Parent
{
public:
int mi; // 编译器没有简单的对同名成员报错,是因为作用域,虽然两个成员的名字相同,但是出于不同的作用域当中;同命名空间的本质是一样的; Child()
{
cout << "Child() : " << "&mi = " << &mi << endl;
}
}; int main()
{
Child c; // Parent() : &mi = 0xbfb43a08 Child() : &mi = 0xbfb43a0c c.mi = ; c.Parent::mi = ; cout << "&c.mi = " << &c.mi << endl; // &c.mi = 0xbfb43a0c,证明直接访问的是子类的 mi;
cout << "c.mi = " << c.mi << endl; // c.mi = 100; cout << "&c.Parent::mi = " << &c.Parent::mi << endl; // &c.Parent::mi = 0xbfb43a08; 作用域分辨符访问父类 mi;
cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1000; return ;
}
1,父类和子类可以产生同名覆盖冲突,但是通过作用域分辨符可以解决这个问 题;
7,再论重载:
1,类中的成员函数可以进行重载:
1,重载函数的本质为多个不同的函数;
2,函数名和参数列表是唯一的标识;
3,函数重载必须发生在同一个作用域中;
8,问题:
1,子类中定义的函数是否能重载父类中的同名函数?
1,将父子间的冲突问题上升到成员函数了;
9,父子间的函数重载编程实验:
1,继承父类成员函数,累加父类的同名成员;
#include <iostream>
#include <string> using namespace std; class Parent
{
public:
int mi; void add(int v)
{
mi += v;
} void add(int a, int b)
{
mi += (a + b);
}
}; class Child : public Parent
{
public:
int mi;
}; int main()
{
Child c; c.mi = ; c.Parent::mi = ; cout << "c.mi = " << c.mi << endl; // c.mi = 100; cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1000; c.add(); // 继承自父类的成员函数;这个函数得到的 mi 不知道后面还要定义一个子类,它知道的 mi 只是父类中的,这个时候 mi 的作用域在父类中,所以给了父类中的 mi 做累加;
c.add(, ); // 继承自父类的成员函数; cout << "c.mi = " << c.mi << endl; // c.mi = 100; cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1006;累加到父类中的 mi 了; return ;
}
2,函数的同名覆盖:
#include <iostream>
#include <string> using namespace std; class Parent
{
public:
int mi; void add(int v)
{
mi += v;
} void add(int a, int b)
{
mi += (a + b);
}
}; class Child : public Parent
{
public:
int mi; void add(int x, int y, int z)
{
mi += (x + y + z);
}
}; int main()
{
Child c; c.mi = ; c.Parent::mi = ; cout << "c.mi = " << c.mi << endl; // c.mi = 100; cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1000; // c.add(1); // 编译器显示没有匹配的函数调用 Child::add(int);同名成员函数覆盖,并没有重载,作用域不同;
// c.add(2, 3); // 编译器显示没有匹配的函数调用 Child::add(int, int);同名成员函数覆盖,并没有重载,作用域不同; c.Parent::add(); // 作用域分辨符解决同名成员函数覆盖问题;
c.Parent::add(, ); // 作用域分辨符解决同名成员函数覆盖问题;累加父类中的 mi c.add(, , ); // 调用子类中的 add(),默认情况下访问的就是子类中的 mi,这个地方发生了同名覆盖; cout << "c.mi = " << c.mi << endl; // c.mi = 115;默认访问的 mi 是子类中的 mi; cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1006;前两次累加的是父类中的 mi; return ;
}
10,父子间的冲突:
1,子类中的函数将隐藏父类的同名函数;
2,子类无法重载父类中的成员函数;
1,因为它们处于不同的作用域;
3,使用作用域分辨符访问父类中的同名函数;
1,类名加上作用域分辨符;
4,子类可以定义父类中完全相同的成员函数;
#include <iostream>
#include <string> using namespace std; class Parent
{
public:
int mi; void add(int v)
{
mi += v;
} void add(int a, int b)
{
mi += (a + b);
}
}; class Child : public Parent
{
public:
int mi; void add(int v) // 同名覆盖;函数重写;
{
mi += v;
} void add(int a, int b) // 同名覆盖;函数重写;
{
mi += (a + b);
} void add(int x, int y, int z) // 重载;
{
mi += (x + y + z);
}
}; int main()
{
Child c; c.mi = ; c.Parent::mi = ; cout << "c.mi = " << c.mi << endl; // c.mi = 100; cout << "c.Parent::mi = " << c.Parent::mi << endl; // c.Parent::mi = 1000; c.add(); // 同名覆盖;
c.add(, ); // 同名覆盖;
c.add(, , ); // 函数重载; cout << "c.mi = " << c.mi << endl; // c.mi = 121;函数同名覆盖和重载,都是默认访问的子类的 mi; cout << "c.Parent::mi = " << c.Parent::mi << endl; // 父类中的函数被同名覆盖,未有访问父类中的 mi; return ;
}
11,小结:
1,子类可以定义父类中的同名成员;
2,子类中的成员将隐藏父类中的同名成员;
1,包括同名成员变量和同名成员函数;
2,重写的依据;
3,这就是同名覆盖;
3,子类和父类中的函数不能构成重载关系;
1,作用域不同;
4,子类可以定义父类中完全相同的成员函数;
1,作用域不同;
5,使用作用域分辨符访问父类中的同名成员;
1,父类名加上作用域分辨符;
C++继承中的同名覆盖的更多相关文章
- 【转】C++中继承中的同名成员问题
C++中,子类若有与父类同名的成员变量和成员函数,则同名的成员变量相互独立,但同名的子类成员函数重载父类的同名成员函数.举例如下: #include <iostream> using na ...
- C++学习笔记-继承中的构造与析构
C++存在构造函数与析构函数,继承中也存在构造和析构函数.继承中的构造和析构函数与普通的构造析构有细微差别. 赋值兼容性原则 #include "iostream" using n ...
- [Java] 继承中,父类被覆盖的成员变量、方法的可访问性
在 Java 的继承机制里,在子类内部,可以访问父类被覆盖的变量和方法:在子类外部,可以访问父类的被覆盖变量,但是不能访问父类的被覆盖方法. 父类中被覆盖的方法不能在外部被方法,这是出于封装的考虑. ...
- 关于Java中继承多接口同名方法的问题
在Java中如果一个类同时继承接口A与B,并且这两个接口中具有同名方法,会怎么样? 动手做实验: interface A{ void fun(); } interface B{ void fun(); ...
- C++ 继承体系中的名称覆盖
首先一个简单的样例: int x; int f() { double x; cin >> x; return x; } 在上述代码中.函数f的局部变量x掩盖了全局变量x.这得从 " ...
- 四. Java继承和多态3. 继承中的方法的覆盖和重载
在类继承中,子类可以修改从父类继承来的方法,也就是说子类能创建一个与父类方法有不同功能的方法,但具有相同的名称.返回值类型.参数列表. 如果在新类中定义一个方法,其名称.返回值类型和参数列表正好与父类 ...
- c#和java中的方法覆盖——virtual、override、new
多态和覆盖 多态是面向对象编程中最为重要的概念之一,而覆盖又是体现多态最重要的方面.对于像c#和java这样的面向对象编程的语言来说,实现了在编译时只检查接口是否具备,而不需关心最终的实现,即最终的实 ...
- Java:类与继承(隐藏和覆盖的问题)
盒子先生金金 Java:类与继承(隐藏和覆盖的问题) Java:类与继承 Java:类与继承 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大特性都离不 ...
- C++中重载、覆盖和隐藏的区别,以及适用场景
一.重载.覆盖和隐藏的区别 二.适用场景 1.重载: 适用于不同的数据类型都需要使用到的功能函数.以数据相加的函数为例,可以在同一个文件内提供以下的重载函数以支持同样的功能: int add(int, ...
随机推荐
- C语言 - strcmp和strncmp的编程实现及总结
一.strcmp和strncmp的编程实现及总结 1.strcmp函数的实现 要求: 原型: int strcmp(char *dest,char * src,int n); 头文件:# ...
- C语言博客作业04数组
0.展示PTA总分 1.本章学习总结 1.1 学习内容总结 1.int a[10];为定义数组,表示数组有10个数 2.数组的下标都是从0开始,到n-1结束 3.数组里元素的个数不能大于数组的长度 4 ...
- 3.决策树ID3算法原理
1.决策树的作用 主要用于解决分类问题的一种算法 2.建立决策树的3中常用算法 1).ID3--->信息增益 2).c4.5--> 信息增益率 4).CART Gini系数 3.提出问题: ...
- springboot + mybatis sql日志
#mapper sql日志 替换成你的mapper接口所在的包名 logging.level.com.example.dao=debug
- MySQ彻底删除与安装配置
彻底删除 1.查看 MySQL 安装了哪些东西 rpm -qa |grep -i mysql 2.卸载 -.el7.x86_64 -.el7.x86_64 .noarch -.el7.x86_64 - ...
- DVWA--Brute Force
这次我们尝试的内容是DVWA的暴力破解 --lower 先抓取一个登陆的包 然后发送到后在Position选项中设置需要破解的变量.Burpsuite会自动设置许多变量,单击“Clear”按钮,把默认 ...
- What’s up with the Graph Laplacian
What's up with the Graph Laplacian? 来源 作者:Jeremy Kun blog: Math ∩ Programming 在数学上图和与图关联的某些矩阵的代数性质有很 ...
- Applink使用原理解析
简介 通过 Link这个单词我们可以看出这个是一种链接,使用此链接可以直接跳转到 APP,常用于应用拉活,跨应用启动,推送通知启动等场景. 流程 在AS 上其实已经有详细的使用步骤解析了,这里给大家普 ...
- oracle性能诊断排查
https://blog.csdn.net/qq_30553235/article/details/78809872 查看oracle用户权限: 1.查看不同用户的连接数 select usernam ...
- C# 强命名程序集,防止dll被修改,混淆下发布
未能加载文件或程序集“Jonckers.Service.RedisCacheEngineExtend, Version=1.0.0.0, Culture=neutral, PublicKeyToken ...