如何访问私有嵌套 class C++ 的 public 构造函数

How can I access public constructor of private nested class C++

我有一个 嵌套的私有 NestedKey 我希望我可以使用我的 add_new_object(Key, Nested) 函数将对象添加到我的 my_mmap 多地图。但是当我尝试调用那些 类 构造函数时,显然它是 不可访问的 。我该如何解决这个问题。

class Enclosing
{
private:
    class Nested {
        string m_str;
        double m_dbl;
        bool m_boolean;
    public:
        Nested(string str, double dbl, bool boolean) :m_str(str), m_dbl(dbl), m_boolean(boolean) {};
    };
    class Key {
        int m_number;
        string m_name;
    public:
        Key(int num, string name) :m_number(num), m_name(name) {};
    };

    Enclosing* singleton;

    std::multimap<Key, Nested> my_mmap;
public:
    void add_new_object_to_mmap(Key k, Nested n) {}


    static Enclosing* get_singleton() {
        static Enclosing instance;
        return &instance;
    }
};

提前谢谢大家!

如果您只需要能够使用构造函数构造 KeyNested,每个构造函数接受 1 个参数,您可以将 add_new_object_to_mmap 制作成成员函数模板并转发参数实际构造函数:

#include <utility>

class Enclosing {
private:
    class Key {
    public:
        Key(int);
        bool operator<(const Key& rhs) const;
        // ...
    };

    class Nested {
    public:
        Nested(double);
        // ...
    };

    std::multimap<Key, Nested> my_mmap;

public:
    template<class Karg, class Narg>
    void add_new_object_to_mmap(Karg&& karg, Narg&& narg) {              
        my_mmap.emplace(std::forward<Karg>(karg), std::forward<Narg>(narg));
    }

    static Enclosing& get_singleton() {
        static Enclosing instance;
        return instance;
    }
};
int main() {
    /*here I want to call constructors*/
    Enclosing::get_singleton().add_new_object_to_mmap(1, 3.141);
}

Demo


要支持使用可变数量的参数构造 KeyNested,您可以使用 std::piecewise_construct:

    template <class... Args>
    void add_new_object_to_mmap(Args&&... args) {
        my_mmap.emplace(std::piecewise_construct, std::forward<Args>(args)...);
    }

forward the arguments as tuples:

int main() {
    Enclosing::get_singleton().
        add_new_object_to_mmap(std::forward_as_tuple(1, "Foo"),
                               std::forward_as_tuple("Str", 3.141, true));
}

Demo

您似乎误解了在私有部分中声明类型的含义。或者至少您不知道这些类型作为 public 成员函数的参数出现的含义。

这是添加了定义的代码(没有 KeyNested 的定义,您根本无法调用它们的构造函数):

#include <map>


class Enclosing
{
private:
    class Nested {};
    class Key {};

    Enclosing* singleton;

    std::multimap<Key, Nested> my_mmap;
public:
    void add_new_object_to_mmap(Key k, Nested n) {}

    
    static Enclosing* get_singleton() {
        static Enclosing instance;
        return &instance;
    }
};

因为类型 KeyNested 出现在 Enclosing 的 public 接口中,它们实际上不是私有的。只有他们的名字是私人的。可以从成员函数中推断出两种类型:

template <typename F> struct get_types;

template <typename K,typename N> struct get_types< void(Enclosing::*)(K,N)> {
    using Key = K;
    using Nested = N;
};

现在你可以像调用任何其他类型的构造函数一样调用它们的构造函数:

int main()
{
    using Types = get_types<decltype(&Enclosing::add_new_object_to_mmap)>;
    using Key = Types::Key;
    using Nested = Types::Nested;
    Enclosing::get_singleton()->add_new_object_to_mmap(Key{},Nested{});
}

Complete Example

最后,请注意调用者甚至不必知道这两种类型的名称。这也适用(或在没有默认构造函数时使用参数):

Enclosing::get_singleton()->add_new_object_to_mmap({},{});

在另一个 class 的私有部分中声明的类型在出现在 public 接口中时不是私有的。如果你真的想对 Enclosing 的用户隐藏这两种类型,那么你需要做一些其他的事情。请参阅 Ted 的回答,了解如何仅将要传递给其构造函数的参数传递给 public add_new_object_to_mmap。那么这两个类型就可以真正私有了。