【问题标题】:Friend functions and derived classes友元函数和派生类
【发布时间】:2025-12-02 10:25:02
【问题描述】:

我正在尝试从定义了友元函数的 Base 派生一个类。我想为我的派生类创建一个使用 Base 的友元函数的友元函数,但保留我的派生类的类型:

#include<algorithm>

class Base
{
public:
  Base(int i, int j, int k)
    {
      vect[0] = i;
      vect[1] = j;
      vect[2] = k;
    }
  ~Base();

  friend Base myMin (const Base& argA,
                     const Base& argB);
protected:
  // Member data
  int vect[3];
};

class Derived : public Base
{
public:
  Derived(int i, int j, int k)
    :
    Base(i,j,k)
    {
    }

  ~Derived();

  friend Derived doSomething(const Derived& argA,
                             const Derived& argB);
};

Base
myMin (const Base& argA,
       const Base& argB)
{
  int i = std::min(argA.vect[0], argB.vect[0]);
  int j = std::min(argA.vect[1], argB.vect[1]);
  int k = std::min(argA.vect[2], argB.vect[2]);
  return Base(i,j,k);
}

Derived doSomething(const Derived& argA,
                    const Derived& argB)
{
  // Does other stuff too...
  return myMin(argA, argB);
}

int main(int argc, char *argv[])
{
  Derived testA(2,4,6);
  Derived testB(3,3,7);

  doSomething(testA,testB);

  return 0;
}

我明白为什么这不起作用(doSomething 被赋予返回 Base,但被告知返回 Derived),并且这可能不是很好的 C++ 形式。我的 Base 类有很多与此类似的友元函数,有没有办法在我的 Derived 类中使用友元函数而无需修改它们?

谢谢

已编辑:错误,供参考,是:

base.H: In function ‘Derived doSomething(const Derived&, const Derived&)’:
base.H:50:26: error: could not convert ‘myMin(const Base&, const Base&)((* &(& argB)->Derived::<anonymous>))’ from ‘Base’ to ‘Derived’
   return myMin(argA, argB);

【问题讨论】:

  • 朋友功能在这里有什么用途?
  • 在示例中的朋友函数访问受保护的类成员。但是这种设计……可以说是次优的。为什么不制作这些函数,虚拟成员函数并使用继承。
  • 在实际代码中,友元函数用于在您不希望修改参数的情况下返回 Base 的新实例(例如 Base baseC = myMin(baseA,baseB);)。此外,由于与现有代码的兼容性,我无法修改现有的 Base 类。我可以添加新成员!我同意这是次优的,不幸的是 Base 已经有 20 年的历史了,还没有最好的设计决策。

标签: c++ inheritance friend-function


【解决方案1】:

最明显的方法是将doSomething() 更改为

 Derived doSomething(const Derived& argA,
                     const Derived& argB)
 {
      Base temp(myMin(argA, argB));
      Derived retval(temp.vect[0], temp.vect[1], temp.vect[2]);
      return retval;
 }

您可能还必须声明 doSomething() 成为 Base 的朋友。

如果不了解您真正想做的事情,很难提供进一步的建议。您完全需要这样做的事实是“代码异味”的一个示例 - 这是您的设计存在缺陷的积极信号,并且随着您的代码不断增长,您将继续需要做这样的变通方法。这逐渐使更改代码变得越来越难 - 每次更改一个部分时,都必须解决其他问题。

【讨论】:

  • 这真的很难看,我想我会尝试找到另一种方法,所以我不使用友元函数(并且我会避免在我的派生类中创建新的)。感谢您的回复!
  • 这就是我的观点。丑陋的变通方法表明您的设计和/或代码中存在更广泛的问题。