你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

C++——父子之间冲突

[复制链接]
gaosmile 发布时间:2020-8-23 22:22
一、父子之间的冲突:
1、思考
子类中是否可以定义父类中的同名成员?
如果可以的话,那么该怎样区分呢?
如果不可以的话,那么又是为啥呢?
代码实践:
#include <iostream>
: ^& `$ g! `2 @6 q! h- |! H#include <string>. O( r6 j0 g: _6 B) |/ |0 i
. n3 D. ^: l# f5 d, `& Z1 u
using namespace std;& \( M, k. K$ P3 F( C8 [) E, ^. S/ `
7 d; O+ ]5 I9 h* C
class Parent
9 Q3 B$ k% V% k{
, p2 \0 u/ ?; [1 _/ x2 I  S5 _- ]public:( s( @6 g" ]0 {+ ^1 z
    int mi;
& U( ?6 n  C+ {& f) p};
/ g, i3 u3 B- S! c5 r( z9 c  z0 V8 U0 r& I$ ^
class Child : public Parent1 k, f3 Q4 y0 d! y5 L
{/ Z0 x- ^* h4 q& z. s. P
public:. N  `" ~& @! I
    int mi;: p% i3 Q1 h) n* _4 t, Y
};0 z. p0 V* E+ [: l
2 ]8 S/ y0 v. F1 P) d4 p4 b4 [
int main()7 {0 c1 {9 [4 [! G3 E; i
{
" s) b0 f; Y$ t  U    Child c;/ }  d- O& M$ u: m' e
    " [- w! p0 ?5 M7 V
    c.mi = 100;    // mi 究竟是子类自定义的,还是从父类继承得到的?0 {4 t- f1 A/ U
   
2 {, N" _( v# J    return 0;: p. C* A* b3 d9 s8 `
}0 |3 }% }/ p+ Y, w4 r" j7 A
代码是否可以编译通过,我们来看一下编译器编译的结果:
root@txp-virtual-machine:/home/txp# g++ test.cpp
3 w1 O! t- y; N# I, d  Uroot@txp-virtual-machine:/home/txp# 4 H: r/ a7 [7 F) L
: b" R0 o" `$ E* O
什么情况,居然可以编译通过,但是你从肉眼看,你看出到底是父类mi还是子类的mi呢,显然我们不能够去瞎猜,那么接下来我们来学习里面的真理!
2、父子之间冲突的规则:
  • 子类可以定义父类中的同名成员
  • 子类中的成员将隐藏父类中的同名成员
  • 父类中的同名成员依然存在于子类中
  • 通过作用域分辨符(:访问父类中的同名成员,例如:
    ! G$ t# d% O; e" ]2 ]4 n6 }
Child c;
, b& u0 b9 b0 I# ?
4 o2 p/ l- x6 V3 m: c$ B1 Ic.mi = 100; //子类中的mi/ U' Y+ L9 g* d0 I: f6 D  ^

2 U4 ?# V  h9 a6 _4 G% Sc.Parent::mi = 1000; // 父类中的mi, I0 o% ~( \/ `* w! l
代码实践:
#include <iostream>
8 @! Y; {" b" ]/ U' ^2 l# d! @#include <string>! b; l/ E4 R) u& x7 ?! p

' H8 Y9 H. M8 l4 ~9 J( Jusing namespace std;
. y# F4 l. [& I2 Z/ p! G
  m# U0 f* @' n5 ?namespace A
. C" i9 k0 N  a6 }( @* M{
$ Z5 l% |# m6 H4 Z# |% x    int g_i = 0;* s" m* r/ @% c/ ^( G3 ?5 G0 G2 z
}
5 A) U5 j; s* D- E! |# B) d$ M, r9 y' b& L$ ^% V5 m
namespace B4 n8 @( R  C7 G7 v. s* V
{
5 a0 s/ y; V# `; J4 J4 R    int g_i = 1;// 同名的全局变量,但是位于两个不同的命名空间;
0 c6 ?7 E- Q8 a5 _}
" W/ {  L+ W1 ?7 k0 W- {$ Q8 W
) t& r$ ^$ O, i# M9 n  e! }6 }8 Nclass Parent
' F0 s7 z' u9 s6 W( W9 ?{
9 a! [) {5 L2 Lpublic:4 M6 M4 v* d$ A2 y
    int mi;% \  S7 I$ t5 q
   
, Z8 V( x4 R$ [  z; s2 C; ~6 t" w    Parent()
. e2 N' }: g+ N8 z  b    {
1 d4 J3 h, }6 v( Q( M        cout << "arent() : " << "&mi = " << &mi << endl;# s( M: k$ [5 k: E
    }$ z  H& F) C# b7 [5 r4 ^
};, `; B! t; m* O1 V- W
" O$ n! W( d6 I6 X) W7 B
class Child : public Parent
  T. n2 b0 {, ]& G& A2 ]4 r{
. m8 n% Z# \1 lpublic:3 l3 |) o: b" X7 }: F- f/ R7 V
    int mi;
' _& R' R; M  p) I8 w   
1 |' j' Y( @& m; b    Child()7 ]$ h" o/ u& g: m' m5 ]) L
    {8 y; Z2 E, b; E8 |
        cout << "Child() : " << "&mi = " << &mi << endl;3 y* [: |' D3 c8 d' ]: G
    }5 ~7 S8 I8 q  O9 _  `4 p
};
0 r2 E: e# \8 W, J' W, Y+ F2 {% P7 c
int main()
5 }( c9 Q- q; c8 d  }) M+ G{
7 {, \9 O, [' I    Child c;
3 B# `: m8 w" T, G$ t0 M   
, C5 F& H6 |8 D    c.mi = 100;    * `& V* i; u. {" j8 T% M0 {4 I' z
    ! b3 n2 F7 l. l5 A! ?( v
    c.Parent::mi = 1000;
* }$ K" X& }* j+ {) ?   
+ r  o! U/ g) D    cout << "&c.mi = " << &c.mi << endl;
! H1 u6 O$ G# ^# K* H5 Q    cout << "c.mi = " << c.mi << endl;; t# O* C' |% r
    : {+ P1 ?/ \: q5 w6 y
    cout << "&c.Parent::mi = " << &c.Parent::mi << endl;" [5 E9 f1 h# _$ X: T* X1 J
    cout << "c.Parent::mi = " << c.Parent::mi << endl;& o" l- c% ^6 p& ]6 N! {
   
$ E/ g: _: \: Z" D    return 0;! g2 g' m9 k( e& K7 g- T
}) L5 M  M5 L8 W; @' _9 a! L
输出结果:
root@txp-virtual-machine:/home/txp# g++ test.cpp, Q% j+ Q  N/ L0 E
root@txp-virtual-machine:/home/txp# ./a.out
. V' Y: S5 e# vParent() : &mi = 0x7ffc270e7bf0
- V7 Y, H/ ?* z% y' o2 nChild() : &mi = 0x7ffc270e7bf4' A# O' T$ H4 ^
&c.mi = 0x7ffc270e7bf4
4 D. C2 y. j$ `, ]- yc.mi = 100
" p4 x- X! ~3 S$ F" G8 r&c.Parent::mi = 0x7ffc270e7bf01 T0 H" Y: I3 J
c.Parent::mi = 1000
1 k$ d& |8 n0 X+ S2 `! |6 o' Q; ]. t0 q6 V% p  A0 T
3、回顾重载:
(1)类中的成员函数可以进行重载
  • 重载函数的本质为多个不同的函数
  • 函数名和参数列表是唯一的标识
  • 函数重载必须发生在同一个作用域中,这一点非常关键

    ! \6 R" D# a9 c# N$ w/ ]5 C
(2)子类中定义的函数是否能够重载父类中的同名函数呢?
代码实践:
#include <iostream>
7 H8 l5 Y( l" H; \! f, E! y, l5 N#include <string>" q  G1 a3 @$ i5 U
7 T9 d1 h  i4 N3 D
using namespace std;/ D# R1 T- U( R7 h( r% [0 ?; j( Y6 j2 @
9 ?+ i. H! {: s8 x
class Parent
% a  G+ |" e0 Q; V! U; N{8 j2 Q2 t! f  E1 m
public:; O$ X7 J) r* f9 P  P9 Y0 m1 y
    int mi;. I0 B# E- b0 [
   
+ f) d+ p# ]% K0 F2 v) V    void add(int v)
3 d. A# O, A2 t+ Y/ E. N& [    {4 a2 _0 m$ u) ]
        mi += v;( k) F! x& a+ `
    }) Y. d+ L4 r% Z
    3 @) H" r$ T/ w; Y3 |% E5 q
    void add(int a, int b)! u/ Z2 ^1 f! g9 z' q
    {. T) U! T3 E% f/ E; g
        mi += (a + b);0 q9 `7 J- j1 I6 O8 H
    }
' p- v, i3 p$ p% Z- P4 K};
. [% g: l* ~0 `1 D
5 H" o, r7 B; v6 E4 `0 P1 pclass Child : public Parent
6 ?# W1 U7 H- B- c2 M9 [{5 P  H- X0 [) p. U8 Y; l
public:- q- u) O8 x( C  a4 p
    int mi;
. M2 O) g! @, @" q    $ C2 R6 G2 S! _, \4 S) E
    void add(int v)
9 W7 @' ?8 p( }8 K2 K    {
( R; y" J( n4 i5 i9 ^2 u        mi += v;
# y# t  r, i( w5 k$ G9 P$ n% s    }
4 Y6 A' C9 ~1 ~/ G# B    3 {% d6 e9 C6 g: V: H
    void add(int a, int b)( k7 ?, ^4 R, B$ x
    {3 ]% F" ?8 R9 u! h# G
        mi += (a + b);# A- i" {% p# J' p" z- d, `. i6 j
    }  B$ R5 O/ g( d- ^# T$ e
   
) f) ~1 {. Q, A: `! p    void add(int x, int y, int z)
9 z* E* a& J+ ]5 n    {0 w/ X9 h8 c5 L2 Q) v+ c/ m  M
        mi += (x + y + z);
3 S3 U1 E9 P" p3 M    }
  a1 l& L( y0 ^; d. ]};
" B& n; o( l& Z9 o' @; x, v8 [! w2 j
int main()
4 _" D4 I. W- u: R* y6 ~{
8 n4 V+ S% Q2 \    Child c;; ]/ x  a, n" z% W1 b/ N: N) K
    3 k+ [! x. M, S% r8 T
    c.mi = 100;   
% o4 ~7 m  r% t  K4 T7 z   
# O* I2 |* U5 O  }- X    c.Parent::mi = 1000;
& ]: ?2 N. f# I0 Q$ h   
# _0 E* k* `; t# `" L4 u    cout << "c.mi = " << c.mi << endl;
1 K" O2 c+ D# }0 u9 q   
; V( |! k, W: W    cout << "c.Parent::mi = " << c.Parent::mi << endl;: W4 `3 L' z( U9 h- a
    ! d' o& x" h7 O  A7 m. a9 O
    c.add(1);
, O; x% L- z. w  p) ?    c.add(2, 3);
( n/ a# Q$ c. ?    c.add(4, 5, 6);
+ S9 \8 \) q9 S  E, y4 K  x/ Q- R' X    * A) R* w. R2 h2 L( g
    cout << "c.mi = " << c.mi << endl;
! T1 B. Q2 e1 r* O1 K* P- J    ; `  ~/ Z3 V& o3 C
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
" W/ b. y9 y, R$ C# a0 Z8 C2 D5 o    * e) U, c4 j6 Z/ D
    return 0;2 b6 R, f! U6 y  I9 V* M, O1 P' r
}
) \/ o* O  G0 F4 q$ i+ J
结果输出:
root@txp-virtual-machine:/home/txp# g++ test.cpp
( Y+ s9 D" j" mroot@txp-virtual-machine:/home/txp# ./a.out
  o" H& A( i3 V! c# `0 p* g$ [4 ^c.mi = 100
9 A, E8 Z4 w, h6 \c.Parent::mi = 1000
, N$ c2 }# Y+ r0 L3 h4 L# vc.mi = 121
, }7 i( E- r4 bc.Parent::mi = 1000
0 V6 w  T# d9 v- {( u7 Y) [
. [# A( j$ r: |3 \4 d
注解:从实验观察来看,函数重名和成员重名的作用一样,子类会覆盖父类的。
为了更加说明这点,我们再来看一个示例:
#include <iostream>! m, T- b# [$ k' N
#include <string>
" E  u4 p! C! a, }9 E, M7 G% x2 r8 S9 B- }# h
using namespace std;  z8 ~. a7 t0 N6 }- Q# t9 c) }6 T
) ~  [* |. P5 j/ g6 _
class Parent! _9 i2 u5 e; T8 w& x
{& g5 j" g& |8 p* q6 U
public:
; [5 A6 N( S+ U9 h    int mi;7 a) f9 p% g- [; t: C( D
    - p- }7 u! x. \# a4 C9 ^! J; ?
    void add(int v)
% F; w. l# d* n2 l  X    {
6 X( D4 C+ I, c# ]8 N        mi += v;: r+ T% Y. [; B2 H# U. F9 q
    }
( y2 j* n: P- ?7 _    $ A# R0 N+ }/ k9 v
    void add(int a, int b)# [- O6 S4 i. i+ v
    {
; I! f6 d  x( a( q. V8 C, B3 @        mi += (a + b);- Q  z% ~0 |* B
    }8 {  b' }& [! F5 X" E) o; W
};
, Y- N5 q5 D4 u) j
2 q, _8 Y2 _/ T, n" q, [  q5 L( kclass Child : public Parent
8 b/ {5 Q  c( y5 {8 ~{
, w1 y" [. h+ \+ Kpublic:( \9 W6 s# j9 l! i# u' r7 I& g
    int mi;3 Y  q8 e; q. G
   
6 J7 e1 d7 _- T" u) y" p1 \- K9 a: @. }   
( G* B- H9 B# J4 F  X  M   
- x2 `; L/ K) Z- R) g. y    void add(int x, int y, int z)' |, J4 L+ [+ e
    {1 f8 |8 f1 W5 ?0 I% B5 ^3 n
        mi += (x + y + z);
5 t4 W4 a; l. C    }9 M% i( S( j/ ?& m. w' j
};* w1 _" F1 T- c5 S
2 d) Z- ~) Q6 K8 S
int main(): f0 T5 m0 E8 ~$ o) W3 n. M
{
, p; o) u; k. e8 k/ G    Child c;
( M6 F( q: H3 W: o4 k, h    " D4 ^5 w) M/ ]. \
    c.mi = 100;    + R/ Z4 e2 {) b4 |* s5 R
    - ]: S, |+ t0 g) k. o! X) w( P+ z) P
    c.Parent::mi = 1000;8 P6 `6 B; l! i' x
    2 {, n+ J8 O, P5 l7 e
    cout << "c.mi = " << c.mi << endl;
! C$ ]- F- ^% p: ~! ?    + J6 L' f4 H+ t4 F" l+ v
    cout << "c.Parent::mi = " << c.Parent::mi << endl;. k6 r5 L8 P: `, J- h  k( Q* D2 X
    : h3 ]9 _( t. U# x
    c.add(1);1 O) X: V8 v) t* F" C! _& @2 V1 |5 W; ?
    c.add(2, 3);, |. W  M  f9 A: M+ U
   c.add(4, 5, 6);
+ o# u) L: l# ?# F/ K    0 t5 _" v! S& g$ u& t+ Z3 q
    cout << "c.mi = " << c.mi << endl;4 W2 V: U/ ^* v+ L
    2 F7 w% l: Z% w3 T
    cout << "c.Parent::mi = " << c.Parent::mi << endl;
! L# ~6 x$ i7 f' M% B1 m- ^   
& C; B: J6 o: N1 D    return 0;
$ ~* b+ N8 l+ G3 Z# }& g4 m}1 n9 u# t( ?2 w1 s
编译结果:
root@txp-virtual-machine:/home/txp# g++ test.cpp; }& q; h- g; z: X
test.cpp: In function ‘int main()’:
4 p+ H" K! V' D# T/ Ntest.cpp:47:12: error: no matching function for call to ‘Child::add(int)’
7 p2 A+ Y- Y3 \4 n/ S  F# P     c.add(1);
2 k6 {9 q9 Q$ F4 w7 E$ M' j  r: N            ^
( |+ C' R4 s+ Z; D0 qtest.cpp:47:12: note: candidate is:' p0 [! l) y5 X$ T, D3 @
test.cpp:29:10: note: void Child::add(int, int, int)4 S# ~! H. `" p
     void add(int x, int y, int z)5 a* H( a* v; Y! s0 L: U
          ^
3 i. N) u  U& r+ K' ~test.cpp:29:10: note:   candidate expects 3 arguments, 1 provided6 Y- ^" K/ k7 Q2 k4 m. D
test.cpp:48:15: error: no matching function for call to ‘Child::add(int, int)’$ y  E; y1 _: D  \2 c
     c.add(2, 3);" B5 V; ^5 H, C1 Z% [0 ~& S
               ^* f4 w9 \, R6 `7 ]3 R4 Q" S3 m/ f
test.cpp:48:15: note: candidate is:( [+ c" \+ Q- O7 m
test.cpp:29:10: note: void Child::add(int, int, int); H$ n  a  n0 }4 Y
     void add(int x, int y, int z)
1 M3 R' }: e3 d" N. q          ^
8 a7 A6 Q6 d4 ~9 @test.cpp:29:10: note:   candidate expects 3 arguments, 2 provided
; ]' m; l5 F& p7 y0 I0 O, m- A7 S3 ]9 w0 G+ i0 L
注解:显示匹配不到add(int)和add(int,int)这两个函数
解决方案,就是利用作用域符分辨符解决问题:
#include <iostream>; a0 N- K" z/ ?/ o+ m5 n% P8 z
#include <string>( \* P# @+ |3 ?' ]5 t  S: v

' R7 k- D8 q7 g+ D7 f* _3 d( R8 ausing namespace std;
% @: @( ]0 A9 L7 t! l$ s" {
4 g. O7 X% q3 _9 u" K/ N6 u3 Y/ V4 C' Aclass Parent
+ Q! l# U* N5 X* w{
0 s* t. w) b1 u( ~% Kpublic:
# g! q$ V& p& z8 J; {* }    int mi;
3 F- M: X& q' H$ G; b0 i0 K3 p) [, K; P
    void add(int v)
3 s: N% ^' S; e7 l    {
9 p8 g3 r: r% M3 U, g! J2 E& N4 W! R        mi += v;
  \  x( |- [4 ^1 j( ^- B/ U    }
% q! W6 X' T% k, t) K
( ^# ?% a, K3 g! d( A5 ~/ |    void add(int a, int b)# u6 K* D  k% w
    {8 Z6 l9 C; ]! Z9 ]# U0 i
        mi += (a + b);( S8 J* |9 {% c: s+ P9 j$ @
    }
; `% ^; k" ^+ z6 r3 \};# z, |0 R2 T, b) z3 v4 O2 z. e. t: C
9 L. Q  X9 b7 p6 [! s  e( |
class Child : public Parent* k0 f& h+ w0 k9 [7 g9 n8 f
{3 ~# b% I# B0 R) o+ z, j8 j! r! x; p
public:
# |- ^$ ?- r! a$ ^1 ~    int mi;
- Z/ L2 H( i% |* ]0 d/ [
# v* C& i) e! d+ b, X* V: w6 p! {6 r) _. {9 H

& ?; J7 R) r) `4 t, }. T    void add(int x, int y, int z)  ~3 W, e' V' ]) f2 F1 a9 [5 A
    {5 A$ I* b" o( `" @
        mi += (x + y + z);  T! f$ {9 ~3 c* s/ I# S4 c/ c) n
    }
2 @* p: U9 M2 K$ G};
; l0 M6 K# o9 O% J* ]$ t
9 y% {0 h+ B+ H4 K% aint main()5 `4 q% w% l  D" S6 U
{; H% M! o8 x" y
    Child c;. Z! T7 r$ A  p: m

1 @! O$ Q' y/ k    c.mi = 100;  Q' Y& K4 w/ v1 K+ p
* l: E* ]( f) F8 G5 t* B& @
    c.Parent::mi = 1000;
4 c' j3 t" E) ?" O
3 V8 F. m0 H) `+ c4 D3 E    cout << "c.mi = " << c.mi << endl;4 [" @( `9 x  B) v  C5 a

$ b2 {- O, a$ v) [: }. Z    cout << "c.Parent::mi = " << c.Parent::mi << endl;
; l/ P6 I1 n" [4 L# c9 }6 m) ~9 g                                       c.Parent::add(1);
) J  q1 L. V- p7 ~. m* s    c.Parent::add(2, 3);: J( |3 e8 |  I3 M) s) ~
   c.add(4, 5, 6);
" f' a2 f% Q) S0 g) W  S9 ?. [! c0 Y& R( c
    cout << "c.mi = " << c.mi << endl;
$ |$ u, ?" L% t  l* J& s
/ }; }6 G7 ^& D    cout << "c.Parent::mi = " << c.Parent::mi << endl;
. }* y' e# T0 Q  i4 u5 N( B- U) S
4 N1 r; J! u9 l5 W* @    return 0;& B& A6 B" L6 e; C5 w. k8 V+ y
}( }8 l0 q9 |, F6 b' V- y% R) T
                                                                                                   
# H( v" b/ T3 s, A2 T& P. U5 }% o  [- G' o/ P0 s3 k# [6 _
输出结果:
root@txp-virtual-machine:/home/txp# ./a.out# l( B+ A4 ~/ |" b7 v
c.mi = 100- y3 ~: M& |& g5 q3 L
c.Parent::mi = 1000, K( R& A: c; ?9 L- i7 x* a
c.mi = 115% ~; t$ A1 o$ d6 T
c.Parent::mi = 10062 L/ b" p) b3 B

, F# p# G6 v# Q' H6 W* x
4、小结:
  • 子类中的函数将隐藏父类的同名函数
  • 子类无法重载父类中的成员函数(不在同一作用域里面)
  • 使用作用域分辨符访问父类中的同名函数
  • 子类可以定义类中完全相同的成员函数

    0 |9 e' p: \- F# o! }8 A4 D
二、总结
  • 子类可以定义父类中的同名成员
  • 子类中的成员将隐藏父类中的同名成员
  • 子类和父类中的函数不能构造重载关系
  • 子类可以定义父类中完全相同的成员函数
  • 使用作用域分辨符访问父类中的同名成员或者函数
    . |. n. A9 y+ k3 }- _
好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。

& C$ N" p0 h& C, E+ D
赞 收藏 评论0 发布时间:2020-8-23 22:22

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版