如何访问私人嵌套类C++的公共构造函数

发布于 2025-01-28 13:53:25 字数 915 浏览 4 评论 0 原文

我有一个嵌套的私有嵌套 key ,我希望我可以使用 add_new_object(key,nested)函数将对象添加到我的 my_mmap multimap。但是,当我试图称这些类构造函数称为无法访问时。我该如何解决问题。

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;
    }
};

谢谢大家!

I have a nested private classes Nested and Key and I want that I could using my add_new_object(Key, Nested) function add objects to my my_mmap multimap. But when I try to call that those classes constructors, obviously that it's inaccessible. How can I solve the problem.

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;
    }
};

Thank you all in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜心小果奶 2025-02-04 13:53:25

您似乎误解了在私人部分中声明类型的含义。或者至少您不知道这些类型作为公共成员功能的参数的含义。

这是您的代码添加的定义(键> nested 的定义,您根本无法调用其构造函数):

#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;
    }
};

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

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{});
}

完整的示例

最后,请注意,呼叫者甚至不必为这两种类型提供名称。这也起作用(或在没有默认构造函数的情况下使用参数):

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

在公共界面中出现在另一类的私有部分中声明的类型不是私有的。如果您真的想从 enclosing 的用户中隐藏两种类型,那么您需要做其他事情。有关如何将仅传递给其构造函数的参数传递给public add_new_object_to_mmap 的方法,请参见TEDS答案。那么两种类型可以是真正的私人。

You seem to misunderstand what it means to declare a type in the private section. Or at least you are not aware of the implications of those types appearing as arguments of a public member function.

Here is your code with definitions added (without a definition for Key and Nested you cannot call their constructor at all):

#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;
    }
};

Because the type Key and Nested appear in the public interface of Enclosing they are not actually private. Only their names are private. It is possible to infer the two types from the member function:

template <typename F> struct get_types;

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

Now you can call their constructor like you call the constructor of any other type:

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

Finally, note that the caller doesn't even have to have names for the two types. This works as well (or with parameters when there are no default constructors):

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

A type declared in the private section of another class is not private when it appears in the public interface. If you really wanted to hide the two types from the user of Enclosing then you need to do something else. See Teds answer for how to pass only parameters to be passed to their constructor to the public add_new_object_to_mmap. Then the two types can be truly private.

一腔孤↑勇 2025-02-04 13:53:25

如果您只需要能够使用每个构造函数构造 key 嵌套每个构造函数每个参数,则可以将 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


支持构建 和code 嵌套带有可变数量的参数,您可以使用 std :: pieceWise_construct

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

and 将参数作为元组

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

If you only need to be able to construct Key and Nested using a constructor taking 1 argument each, you could make add_new_object_to_mmap into a member function template and forward the arguments to the actual constructors:

#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


To support constructing Key and Nested with a variable amount of arguments, you could use std::piecewise_construct:

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

and 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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文