如何从友元函数访问受保护的构造函数?

时间:2015-11-24 19:18:04

标签: c++ friend-function

我创建了一个类,我想强制任何尝试构建对象的人使用unique_ptr。为此,我想到声明构造函数protected并使用返回friend的{​​{1}}函数。所以这是我想要做的一个例子:

unique_ptr

我做了一些关于朋友函数的阅读,我理解朋友函数可以访问类对象的私有/受保护成员。

无论如何,我可以让我的榜样有用吗?

即使没有朋友功能,我的目标也是让某人创建对象的template <typename T> class A { public: friend std::unique_ptr<A<T>> CreateA<T>(int myarg); protected: A(int myarg) {} }; template <typename T> std::unique_ptr<A<T>> CreateA(int myarg) { // Since I declared CreateA as a friend I thought I // would be able to do that return std::make_unique<A<T>>(myarg); } 唯一方式。

修改

我稍微更改了代码。我没有提到我的类有一个模板参数。这显然使事情变得更加复杂。

3 个答案:

答案 0 :(得分:3)

你可以这样做: -

#include <iostream>
#include <memory>
using namespace std;
class A
{
    int arg;
public:
    friend unique_ptr<A> CreateA(int myarg);
    void showarg() { cout<<arg; }

protected:
    A(int myarg): arg(myarg) {}
};
unique_ptr<A> CreateA (int myarg)
{
    return std::unique_ptr<A>(new A(myarg));
}
int main()
{
    int x=5;
    unique_ptr<A> u = CreateA(x);
    u->showarg();
    return 0;
}

输出: -

5

如果您不想使用friend功能,可以使功能static&amp;这样称呼: -

unique_ptr<A> u = A::CreateA(x);

编辑: -

在回复你的编辑时,我改写了程序&amp;它是这样的: -

#include <iostream>
#include <memory>
using namespace std;
template <typename T>
class A
{
    T arg;
public:
    static std::unique_ptr<A> CreateA(T myarg)
    {
        return std::unique_ptr<A>( new A(myarg) );
    }
    void showarg()
    {
        cout<<arg;
    }
protected:
    A(T myarg): arg(myarg) {}
};

int main()
{
    int x=5;
    auto u = A<int>::CreateA(x);
    u->showarg();
    return 0;
}

简单&amp;简单 !!!但请记住,您无法实例化object of A。祝你好运!!!

答案 1 :(得分:2)

创建一个实例化受保护构造函数的静态函数。

  #include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include <memory>
using namespace std;
template< typename T >
class A
{
public:
    static void CreateA(int myarg, std::unique_ptr<A<T>>& objA, T t) {
        std::unique_ptr<A<T>> objB(new A(myarg, t));
        objA = std::move(objB);
    }

protected:
    A(int myarg, T t) {
        m_t = t;
    }

private:
    T m_t;
};

int main() {

    int myArg = 0;
    std::unique_ptr<A<int>> anotherObjA;
    A<int>::CreateA(myArg, anotherObjA, myArg);


    return 0;
}

答案 2 :(得分:2)

其他答案建议使用静态模板功能,我同意这是最好的解决方案,因为它更简单。

我的回答解释了为什么你的朋友方法没有工作以及如何正确使用朋友方法。

原始代码中存在两个问题。一个是make_unique实际上并不是A的朋友,因此调用make_unique<A<T>>(myarg);无法访问A的受保护构造函数。为避免这种情况,您可以改用unique_ptr<A<T>>(new A(myarg))。从理论上讲,可以宣称make_unique是朋友,但我甚至不确定正确的语法。

另一个问题是the template friends problem。在类模板中,friend <function-declaration>实际上声明了一个非模板的朋友。

C ++ FAQ提供了两种可能的解决方法。其中之一是定义内联的朋友函数。但是,在这种情况下,函数只能通过参数依赖查找找到。但由于该函数不以A<T>(或A<T> &)作为参数,因此永远不会以这种方式找到它。因此,此选项对您的情况不可行 - 它更适合于运算符重载。

所以唯一的解决方法是在类定义之前声明(并可选地定义)模板函数:

#include <memory>

template<typename T>
class A;

template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
    return std::unique_ptr<A<T>>{new A<T>(myarg)};
}

template <typename T>
class A
{
    friend std::unique_ptr<A<T>> CreateA <> (int myarg);
//          refers to existing template  ^^

protected:
    A(int myarg) {}
};

int main()
{
    auto x = CreateA<int>(5);
}

注意:可以在我定义它的地方声明CreateA,然后再放置函数定义。但是,我发布的代码仍有效 - 尽管在A出现在源代码中时未定义new A<T>(myarg) - 因为CreateA在调用之前未实例化A,此时{{1}} 1}}将被定义。