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
相关产品推荐
相关产品推荐

