MST

星途 面试题库

面试题:C++友元函数与成员函数实现运算符重载在多态性上的差异

已知C++可以通过友元函数和成员函数实现运算符重载,在涉及多态性的场景下,例如虚函数和运行时多态,这两种实现方式在行为和应用上会有哪些差异?请举例说明。
29.2万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
  1. 成员函数实现运算符重载
    • 行为
      • 成员函数是类的一部分,它的调用依赖于类的对象。对于虚函数和运行时多态,成员函数可以被声明为虚函数。当通过基类指针或引用调用虚成员函数时,会根据对象的实际类型来决定调用哪个派生类的版本,实现运行时多态。
      • 在运算符重载中,如果使用成员函数重载运算符,this指针指向调用该运算符的对象,操作数是隐含的。例如,对于a + b,如果+运算符是通过成员函数重载,a是调用对象,b是参数。
    • 应用:适用于需要根据对象的实际类型进行不同操作的场景,并且操作与类紧密相关。
    • 示例
#include <iostream>

class Base {
public:
    virtual Base operator+(const Base& other) const {
        std::cout << "Base::operator+" << std::endl;
        return *this;
    }
};

class Derived : public Base {
public:
    Base operator+(const Base& other) const override {
        std::cout << "Derived::operator+" << std::endl;
        return *this;
    }
};

int main() {
    Base* basePtr1 = new Base();
    Base* basePtr2 = new Derived();

    Base result1 = *basePtr1 + *basePtr1;
    Base result2 = *basePtr2 + *basePtr1;

    delete basePtr1;
    delete basePtr2;

    return 0;
}

在上述代码中,operator+是虚函数,通过basePtr1调用时,调用Base::operator+,通过basePtr2调用时,调用Derived::operator+,实现了运行时多态。

  1. 友元函数实现运算符重载
    • 行为
      • 友元函数不是类的成员,它没有this指针。友元函数不能被声明为虚函数,因为虚函数机制依赖于对象的虚函数表,而友元函数不属于任何类对象。所以在涉及多态性方面,友元函数只能基于参数的静态类型进行操作,无法实现运行时多态。
      • 对于运算符重载,友元函数的所有操作数都显式地作为参数传递。例如,对于a + bab都是operator+友元函数的参数。
    • 应用:当运算符的操作数类型不同,并且希望对所有操作数进行同等处理,或者希望运算符的行为不依赖于特定对象类型时使用。
    • 示例
#include <iostream>

class Base {
    friend Base operator+(const Base& a, const Base& b);
};

Base operator+(const Base& a, const Base& b) {
    std::cout << "Base::operator+(friend)" << std::endl;
    return a;
}

class Derived : public Base {};

int main() {
    Base base1;
    Derived derived1;

    Base result = base1 + derived1;

    return 0;
}

在这个例子中,operator+是友元函数,无论derived1实际类型是什么,调用的都是基于参数静态类型的Base::operator+(friend)函数,无法实现运行时多态。

总结来说,成员函数实现运算符重载可以利用虚函数机制实现运行时多态,而友元函数实现运算符重载不能实现运行时多态,只能基于参数的静态类型进行操作。