C++必看:关于多态下基类函数参数的调用问题

在C++中,虚函数与多态密切相关,特别是运行时多态(也称为动态多态)。当一个类中定义了虚函数,并且通过基类指针或引用调用该函数时,实际执行的函数版本将根据对象的动态类型在运行时确定。这种机制依赖于虚函数表(vtable)和虚指针(vptr),由编译器在后台自动管理。

虚函数与运行时多态的基本原理

在C++中,运行时多态的实现依赖于以下条件:

  1. 基类中声明了虚函数(使用virtual关键字)。
  2. 派生类重写了该虚函数。
  3. 通过基类指针或引用调用该虚函数。

例如:

#include <iostream>
class Base {
public:
    virtual void func() {
        std::cout << "Base::func()" << std::endl;
    }
};

class Derived : public Base {
public:
    void func() override {
        std::cout << "Derived::func()" << std::endl;
    }
};

int main() {
    Base* ptr = new Derived();
    ptr->func(); // 输出: Derived::func()
    delete ptr;
    return 0;
}

在这里,ptr是一个指向Base类型的指针,但实际指向Derived对象。由于func是虚函数,运行时会根据对象的实际类型调用Derived::func(),这就是运行时多态。

函数参数指针是否“生效”

虚函数的多态行为与函数的参数类型无关,而只与调用该函数的对象的动态类型有关。参数是指针还是其他类型,不会改变运行时多态的机制。

例如,考虑以下代码:

#include <iostream>
class Base {
public:
    virtual void func(int* ptr) {
        std::cout << "Base::func() with pointer " << ptr << std::endl;
    }
};

class Derived : public Base {
public:
    void func(int* ptr) override {
        std::cout << "Derived::func() with pointer " << ptr << std::endl;
    }
};

int main() {
    int value = 42;
    int* p = &value;
    Base* basePtr = new Derived();
    basePtr->func(p); // 输出: Derived::func() with pointer <address>
    delete basePtr;
    return 0;
}

在此例中,func接受一个int*类型的指针参数。调用basePtr->func(p)时,仍然会根据basePtr指向的实际对象类型(Derived)执行Derived::func()。参数p只是被传递给函数,不影响多态的决议过程。

如果参数是指向基类的指针

虚函数的多态性仅适用于调用该函数的对象(即this指针所指向的对象),而不适用于函数参数的类型。例如:

#include <iostream>
class A {
public:
    virtual void print() { std::cout << "A" << std::endl; }
};

class B : public A {
public:
    void print() override { std::cout << "B" << std::endl; }
};

class Base {
public:
    virtual void func(A* a) {
        a->print();
        std::cout << "Base::func()" << std::endl;
    }
};

class Derived : public Base {
public:
    void func(A* a) override {
        a->print();
        std::cout << "Derived::func()" << std::endl;
    }
};

int main() {
    Base* basePtr = new Derived();
    A* aPtr = new B();
    basePtr->func(aPtr); // 输出: B 然后 Derived::func()
    delete basePtr;
    delete aPtr;
    return 0;
}

在这里,func的参数a是一个A*类型的指针,指向B对象。调用basePtr->func(aPtr)时:

  1. basePtr的动态类型是Derived,因此调用Derived::func()
  2. func内部,a->print()根据aPtr的动态类型(B)调用B::print()
    两者的多态行为是独立的:basePtr的多态决定调用哪个func,而aPtr的多态决定调用哪个print

总结

  • 虚函数的运行时多态与函数参数的类型(包括是否为指针)无关,多态仅取决于调用该函数的对象的动态类型。
  • 如果参数是指针类型,它会被正常传递给虚函数,但不会影响虚函数本身的决议过程。
  • 如果参数本身是指向基类的指针,其自身的多态行为(如调用其虚函数)与调用者的多态行为是分开的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值