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,父类名加上作用域分辨符;

05-23 03:35