2017-03-12 61 views
1

我创建了基类指针并为它分配了新的派生类。分配给派生类的基类指针

class Base 
{ 
public: 
    virtual void f(int); 
    virtual void f(double); 
    virtual void g(int i = 10); 
}; 

void Base::f(int) 
{ 
    cout << "Base::f(int)" << endl; 
} 

void Base::f(double) 
{ 
    cout << "Base::f(double)" << endl; 
} 

void Base::g(int i) 
{ 
    cout << i << endl; 
} 

class Derived: public Base 
{ 
public: 
    void f(complex<double>); 
    void g(int i = 20); 
}; 

void Derived::f(complex<double>) 
{ 
    cout << "Derived::f(complex)" << endl; 
} 

void Derived::g(int i) 
{ 
    cout << "Derived::g() " << i << endl; 
} 

void main() 
{ 
    Base b; 
    Derived d; 
    Base* pb = new Derived; 
    b.f(1.0); 
    d.f(1.0); 
    pb->f(1.0); 
    b->g(); 
    d->g(); 
    pb->g(); 
    delete pb; 
} 

结果是:

b和d
Base::f(double) 
Derived::f(complex) 
Base::f(double) 
10 
Derived::g() 20 
Derived::g() 10 

结果预计。 pb-> f(1.0)调用基函数f(double),但pb-> g()似乎调用派生类函数g,但使用参数i = 10从基类。为什么?

+2

为什么?因为您正在静态使用'Base'接口,所以派生到'Derived :: pb'只在运行时发生。 –

+0

'delete pb;'会导致未定义的行为,因为Base没有虚拟析构函数 –

回答

2

Kerrek SB在评论中说了这一切,我会详细介绍一下。

this answer一样,解析默认函数参数的机制发生在编译时。当编译器看到pb->g();,知道pbBase*类型的指针,将查询的Base::g声明,即

virtual void g(int i = 10); 

它的结论:

1-丢失的参数i应该被设置为10这是一个编译时决定。

2-该方法被声明为虚拟,这意味着实际调用的方法取决于pb将在运行时指向什么。编译器设置机制在运行时将调用发送到g(通常通过通过vtable的间接寻址)。由于在运行时它发生pb实际上指向Derived类型的对象,调用方法Derived::g

相关问题