例子1:属性的覆盖
#include "stdafx.h"

class A {
public:
int i;
A() { i=1; }
};

class B: public A {
public:
int i;
B() { i=2; }
};

class C: public B {
public:
int i;
C() { i=3; }
};

int main(int argc, char* argv[])
{
A* a1 = new A(); printf(" %d\n", a1->i);
A* a2 = new B(); printf(" %d\n", a2->i);
A* a3 = new C(); printf(" %d\n", a3->i);

printf(" %d\n", ((B*)a2)->i);
printf(" %d\n", ((B*)a3)->i);
printf(" %d\n", ((C*)a3)->i);

return 0;
}

输出:
1
1
1
2
2
3
结论:按照指针的定义类型来读取相关类的属性。大概三个属性在内存里都存在。有虚函数,但是没有虚数据成员!指针是什么类型(不管它指向什么对象),数据成员就是什么。

printf(" %d\n", sizeof(*a1)); // 这里,也是严格按照指针类型走。
printf(" %d\n", sizeof(*a2));
printf(" %d\n", sizeof(*a3));

同理:
int main(int argc, char* argv[])
{
A a1; printf(" %d\n", a1.i);
B a2; printf(" %d\n", a2.i);
C a3; printf(" %d\n", a3.i);

printf(" %d\n", ((A)a2).i); // 向上强制转换,变成A类型对象,则读取A的i
printf(" %d\n", ((B)a3).i); // 向上强制转换,变成B类型对象,则读取B的i

return 0;
}
输出:
1
2
3
1
2
结论:按照对象类型来读取相关类的数据成员。完全与Java一致。
(与Java比较,Java只有指针类型,而没有对象类型,即只要研究前一种情况即可)

例子2.1:误入函数参数的强制转换
#include "stdafx.h"

class A {
public:
virtual void get(int i) { printf("int in A: %d\n", i); }
virtual void get(double d) { printf("double in A: %f\n", d); }
};

class B: public A {
public:
virtual void get(int i) { printf("int in B: %d\n", i); }
};

int main(int argc, char* argv[])
{
A* pA = new A(); pA->get(1); pA->get(2.2);
A* pAB = new B(); pAB->get(1); pAB->get(2.2);
B* pB = new B(); pB->get(1); pB->get(2.2); // warning

return 0;
}
编译:
warning C4244: 'argument' : conversion from 'const double' to 'int', possible loss of data
输出:
int in A: 1
double in A: 2.200000
int in A: 1
double in A: 2.200000
int in B: 1
int in B: 2 // 注意,C++更倾向于做参数的强制转换,好继续调用int,而不是调用父类函数的get(double d)。但这不是覆盖父类同名函数覆盖

int main(int argc, char* argv[])
{
A a; a.get(1); a.get(2.2);
A ab; ab.get(1); ab.get(2.2);
B b; b.get(1); b.get(2.2); // warning

return 0;
}
编译:
warning C4244: 'argument' : conversion from 'const double' to 'int', possible loss of data
输出:
int in A: 1
double in A: 2.200000
int in A: 1
double in A: 2.200000
int in B: 1
int in B: 2 // 注意,C++更倾向于做参数的强制转换,好继续调用int,而不是调用父类函数的get(double d)。但这不是覆盖父类同名函数覆盖

结论:函数参数强制转换后的调用优先级比父类虚拟函数更高

注意:
1. C++函数不是默认virtual的。所以把上面的virtual都去掉的话,也会掉入那个参数强制转换的陷阱。
2. C++默认属性是private(如果不写明的话)

例子2.2:似乎存在子类一个函数覆盖父类全部同名函数的问题(还是有点怀疑),这点与Java不一样。
#include "stdafx.h"

class A {
private:
int i;
public:
A() { i=3; }
virtual void get(int i) { printf("int in A: %d\n", i); }
virtual void get(A a) { printf("double in A: %d\n", i); } // 注意,如果这里写%f编译没错,运行出错。可能double占的字节更多吧。
};

class B: public A {
private:
int i;
public:
B() { i=4; }
virtual void get(int i) { printf("int in B: %d\n", i); }
};

int main(int argc, char* argv[])
{
A a; a.get(1); a.get(a);
A ab; ab.get(1); ab.get(a);
B b; b.get(1);
b.get(a); // 编译不过,说不能把A转成int

return 0;
}

注意,这个例子还深挖一下,因为有一个private i,如果同名函数调用的话,到底调用谁呢?试了,数据成员跟着对象类型走。

例子3:测试静态函数覆盖问题
#include "stdafx.h"

class A {
private:
int i;
public:
A() { i=3; }
static void get(int i) { printf("int in A: %d\n", i); }
};

class B: public A {
private:
int i;
public:
B() { i=4; }
static void get(int i) { printf("int in B: %d\n", i); }
};

int main(int argc, char* argv[])
{
A::get(1);
B::get(2);
A a; a.get(1);
B b; b.get(2);
((A)b).get(3); // 里,按转换后的A类型调用静态函数
A* pa = new A(); pa->get(1);
A* pab = new B(); pab->get(1); // 这里,按指针类型A调用静态函数(静态函数是死脑筋,死跟着最简单的指针类型走,不像虚函数那样脑筋灵活)
B* pb = new B(); pb->get(2);
((A*)pb)->get(2); // 这里,按转换后的指针类型调用静态函数

return 0;
}
输出:
int in A: 1
int in B: 2
int in A: 1
int in B: 2
int in A: 3
int in A: 1
int in A: 1
int in B: 2
int in A: 2

结论:静态函数跟着指针类型走(毕竟静态函数不是虚拟函数),而不是指针指向的对象类型走。这一点,跟数据成员一致。

注意:静态函数不能调用对象的属性,以下是无法编译通过的:

class A {
private:
int i;
public:
A() { i=3; }
static void get() { printf("int in A: %d\n", i); }
};

C++的同名属性(没有虚拟属性)、同名普通函数、同名静态函数(没有虚拟静态函数),是否被覆盖的更多相关文章

  1. schema中的虚拟属性方法

    schema中的虚拟属性方法相当于vue中的计算属性,它是通过已定义的schema属性的计算\组合\拼接得到的新的值 var personSchema = new Schema({ name: { f ...

  2. C#中对虚拟属性和抽象属性的重写有什么异同

           public abstract class A         {             //抽象属性不能有实现代码             public abstract strin ...

  3. Python类属性,实例属性

    1.Python类数据属性:定义在类里面但在函数外面的变量,它们都是静态的. #一段很简单的代码,但反应了很多 >>> class A(): a=1 #一个类里面有个属性a > ...

  4. Python中的类属性、实例属性与类方法、静态方法

    1.什么是类对象,实例对象 类对象:类名 实例对象:类创建的对象 2.类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++.Java中类的静态成员变量有点 ...

  5. JS 本地属性与继承属性

    判断是否拥有某种属性 1.in 运算符 var obj = {name:'jack'}; alert('name' in obj); // --> true alert('toString' i ...

  6. C语言中的作用域、链接属性与存储属性

    C语言中的作用域.链接属性与存储属性 一.作用域(scope) 代码块作用域 表示{}之间的区域,下例所示,a可以在不同的代码块里面定义. #include<stdio.h> int ma ...

  7. Python3 之 类属性与实例属性

    1.类属性与实例属性 类属性就相当与全局变量,实例对象共有的属性,实例对象的属性为实例对象自己私有. 类属性就是类对象(Tool)所拥有的属性,它被所有类对象的实例对象(实例方法)所共有,在内存中只存 ...

  8. python的类属性、实例属性、类方法、静态方法

    类属性 就像如下代码: class Person: name = "张三" # 共有类属性 __age = 18 # 私有类属性 在类中直接定义的属性就是类属性,它被所有的实例对象 ...

  9. Python基础:17类和实例之一(类属性和实例属性)

    1:类通常在一个模块的顶层进行定义.对于Python来说,声明与定义类是同时进行的. 2:类属性仅与其类相绑定,类数据属性仅当需要有更加“静态”数据类型时才变得有用,这种属性是静态变量.它们表示这些数 ...

  10. The related functions and attributes for managing attributes - 操作属性的重要属性和函数

    特性 property 都是类属性(静态变量),但是特性管理的其实是实例属性的存取, ****** 回顾 -'类方法' classmethod 和 '静态方法' staticmethod 皆可以访问类 ...

随机推荐

  1. Anaconda是如何进行版本管理的?

    创建不同的environments,在电脑中会有不同的文件夹 然后,当使用conda下载时,会下载到不同的env文件夹下(提前进行env切换) 那么不是在anaconda prompt命令行下下载的呢 ...

  2. js控制手机保持亮屏的库,解决h5移动端,自动息屏问题

    一些说明:我用Laya(ts)开发小游戏,有需要保持手机屏幕常亮的需求(非必须的),然后作为小白的我就在网上找到了这个库,大概了解下,应该是通过播放空视频的原理来保持手机屏幕常亮,然后就放到项目中试了 ...

  3. Loadrunner参数化避免重复数据

    1.我们性能测试过程中经常遇到需要创建很多数据来运行测试场景,但是如果数据准备不够多,可能会造成数据不够用,导致场景运行失败,下面简单的例子: 2.我们对用户名分别使用VuserID和lteratio ...

  4. EM 算法资料

    EM 算法的英文全称是: Expectation-Maximum. EM 算法的步骤 假设 \(Z\) 是隐变量,\(\theta\) 是待定参数. E 步:固定参数 \(\theta\),求 \(Z ...

  5. CentOS 7 安装wps2019

    1. download https://www.wps.cn/product/wpslinux 2. rpm 安装缺少lib包,于是yum 安装 .x86_64.rpm 3.安装完成,运行的时候又报错 ...

  6. python基础之 数据格式化

    %还是format 皇城PK Python中格式化字符串目前有两种阵营:%和format,我们应该选择哪种呢? 自从Python2.6引入了format这个格式化字符串的方法之后,我认为%还是form ...

  7. 15 可视化工具 Navicat的简单使用

    本节重点: 掌握Navicat的基本使用 # PS:在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作My ...

  8. 第五周总结&实验报告三

    第五周总结&实验报告三 实验报告 1.已知字符串:"this is a test of java".按要求执行以下操作:(要求源代码.结果截图.) ① 统计该字符串中字母s ...

  9. jquery.fileupload-image-editor.js 中actions.resizeImage

    https://github.com/ChuckForkJS/jQuery-File-Upload/blob/master/js/jquery.fileupload-image-editor.js a ...

  10. 四十一、python面向对象二

    A.成员: 1.字段:静态字段(每个对象都有同一字段),普通字典(每个对象都有不同的数据) 2.方法:静态方法(无需使用对象的内容),类方法,普通方法(使用对象中的数据) 3.特性:普通特性(将方法伪 ...