You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++类型擦除场景下内部类无法找到友元函数的编译问题求助

问题根因

这个编译错误是名字查找优先级导致的:
在ShapeModel类的成员函数serialize()/draw()内部调用同名函数时,编译器会优先匹配当前类自身的成员函数(也就是你重写的虚函数void serialize() const和void draw(int x, int y) const),不会继续查找全局作用域下针对Circle/Square重载的同名自由函数,因此出现参数数量不匹配的报错。

另外还有两个次要问题会导致后续报错:

  • drawAllShapes函数中调用draw时传入了0.0(double类型),和draw接口要求的int参数类型不匹配
  • Shape类的四个特殊成员函数仅声明未实现,会触发链接错误

修复方案

只需要对ShapeModel内的函数调用加上全局作用域限定符::,强制编译器从全局作用域查找对应的重载函数,再修正次要问题即可。


修复后完整代码

#include <iostream>
#include <memory>
#include <vector>

class Circle 
{ 
 public: 
   explicit Circle( double rad ) 
      : radius{ rad } 
      // ... Remaining data members 
   {} 
   double getRadius() const noexcept { return radius; }
   // ... getCenter(), getRotation(), ... 
 private: 
   double radius; 
   // ... Remaining data members 
};

class Square 
{ 
 public: 
   explicit Square( double s ) 
      : side{ s } 
      // ... Remaining data members 
   {} 
   double getSide() const noexcept { return side; }
   // ... getCenter(), getRotation(), ... 
 private: 
   double side; 
   // ... Remaining data members 
};

class Shape 
{ 
 private:
    struct ShapeConcept 
    { 
       virtual ~ShapeConcept() {} 
       virtual void serialize() const = 0; 
       virtual void draw(int x, int y) const = 0; 
       virtual std::unique_ptr<ShapeConcept> clone() const = 0; 
    }; 

    template< typename T > 
    struct ShapeModel : ShapeConcept 
    { 
       ShapeModel( T&& value ) 
          : object{ std::forward<T>(value) } 
       {} 
       
       std::unique_ptr<ShapeConcept> clone() const override 
       { 
          return std::make_unique<ShapeModel>(*this); 
       } 
       void serialize() const override 
       { 
          ::serialize( object ); // 加::限定全局作用域
       } 
       void draw( int x, int y ) const override 
       { 
          ::draw( object, x, y ); // 加::限定全局作用域
       } 
       T object; 
    };

    friend void serialize( Shape const& shape )
    { 
       shape.pimpl->serialize(); 
    }
    friend void draw( Shape const& shape, int x, int y )
    { 
       shape.pimpl->draw( x, y ); 
    }

    std::unique_ptr<ShapeConcept> pimpl; 
 public: 
   template< typename T > 
   Shape( T&& x ) 
      : pimpl{ new ShapeModel<T>( std::forward<T>(x) ) } 
   {} 
   // 补全特殊成员函数实现
   Shape( Shape const& s ) : pimpl(s.pimpl->clone()) {}
   Shape( Shape&& s ) noexcept = default;
   Shape& operator=( Shape const& s ) {
       if (this != &s) pimpl = s.pimpl->clone();
       return *this;
   }
   Shape& operator=( Shape&& s ) noexcept = default;
};


void serialize( Circle const& circle ) {
    std::cout << "Serializing a circle with radius "
        << circle.getRadius() << std::endl;
} 
void draw( Circle const& circle, int x, int y ) {
    std::cout << "Drawing a circle with radius "
        << circle.getRadius() << " Coordinates ("
        << x << ", " << y << ")" << std::endl;
}
void serialize( Square const& square ) {
    std::cout << "Serializing a square with side "
        << square.getSide() << std::endl;
} 
void draw( Square const& square, int x, int y ) {
    std::cout << "Drawing a square with side "
        << square.getSide() << " Coordinates ("
        << x << ", " << y << ")" << std::endl;
} 

void drawAllShapes( std::vector<Shape> const& shapes ) 
{ 
   for( auto const& shape : shapes ) 
   { 
      draw( shape , 0, 0 ); // 把double类型的0.0改成int类型的0
   } 
}
int main() 
{ 
   using Shapes = std::vector<Shape>; 
   // Creating some shapes 
   Shapes shapes; 
   shapes.emplace_back( Circle{ 2.0 } ); 
   shapes.emplace_back( Square{ 1.5 } ); 
   shapes.emplace_back( Circle{ 4.2 } ); 
   // Drawing all shapes 
   drawAllShapes( shapes ); 
}

运行输出:

Drawing a circle with radius 2 Coordinates (0, 0)
Drawing a square with side 1.5 Coordinates (0, 0)
Drawing a circle with radius 4.2 Coordinates (0, 0)

内容的提问来源于stack exchange,提问作者user2183336

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 15:45:03