带有枚举类参数的静态成员变量的 friend 函数

friend function to static member variable with enum class parameter

提问人:Tomáš Nadrchal 提问时间:8/3/2023 最后编辑:Tomáš Nadrchal 更新时间:8/4/2023 访问量:46

问:

我在命名空间 N 中有 2 个类,类 A类 BA 类具有 B 类容器。 B 将结构 S 作为私有静态成员(每个对象 B 的设置)。私有的原因是我想通过类 A 访问这个静态成员。 所以我在类 A 中有成员函数,它设置类 B 的私有静态成员。 在 B 中使用效果很好,但是我想限制它,只有类 A 的成员函数 setC类 B 的朋友。 另一件事是,在类 A 中,我有枚举类 Type,它有助于在结构体 S 中设置相应的变量。friend class A;

如何使用 setS 作为 B 类的友元函数?

注意: 为了便于阅读,我将两个类都放在单独的文件中,我希望拥有它。

简约代码示例:

A.hpp(阿普普)

#ifndef A_HPP
#define A_HPP

#include "B.hpp"
#include <vector>

namespace N
{
class B;
class A
{
public:
    enum class Type
    {
        one,
        two,
    };
    A();
    void addValue (int value);
    void printContainer ();
    void setS (Type type, int number);
    void printS ();

private:
    std::vector<B> container;
};

} // namespace N
#endif // A_HPP

B.hpp - 内部实现,使其变得简单

#ifndef B_HPP
#define B_HPP

#include "A.hpp"
#include <iostream>

namespace N
{
class A;
class B
{
public:
    B(int val) :
        value (val)
    {
    }
    // friend class A; this works as it should
    friend void A::setS(A::Type type, int number); // error N::A::Type has not been declared
    void print () {std::cout << "Value: " << value << "\n";}
    static inline void printS () {std::cout << s.first << " | " << s.second << std::endl;}

private:
    struct S
    {
        int first;
        int second;
    };
    static inline S s;
    int value;
};

} // namespace N
#endif // B_HPP

A.cpp - 实现

#include "A.hpp"
#include "B.hpp"

namespace N
{
A::A()
{
    // empty ctor
}

void A::setS(Type type, int number)
{
    switch (type)
    {
        case Type::one:
            B::s.first = number;
            break;
        case Type::two:
            B::s.second = number;
            break;
    }
}

void A::printS ()
{
    B::printS();
}

void A::addValue (int value)
{
    container.push_back(value);
}

void A::printContainer ()
{
    for (auto& value : container)
    {
        value.print();
    }
}
} // namespace N

main.cpp 只是为了完整的例子

#include "A.hpp"
#include <iostream>

int main ()
{
    N::A a;
    a.setS(N::A::Type::one, 5);
    a.printS();

    a.addValue(1);
    a.addValue(2);
    a.addValue(3);
    a.printContainer();
    std::cout << std::flush;

    return 0;
}
C++ 枚举 静态 友元

评论

0赞 BoP 8/3/2023
问题是标头相互包含。因此,当 B.hpp 包含 A.hpp 时,A 标头保护已处于活动状态,因此 A 类成员不可见。
0赞 Aconcagua 8/3/2023
另一个问题: – 您也不能预先声明嵌套类型,C++ 根本不支持(不幸的是)。A::Type
0赞 Eljay 8/3/2023
我会创建一个独立的函数,而不是 的成员函数,因为它没有理由需要成为成员函数。这将使相互依存关系(先有鸡还是先有蛋的问题)脱钩。(似乎是 和 的命名混淆。但是,由于“C++旨在防止墨菲,而不是马基雅维利。也许只是让所有 A 都成为朋友。这些类已经紧密相连了——我会把它们放在同一个头文件中。另一种选择是建立一个共同的朋友中介类,作为中间人。setSAsetSsetC
1赞 Jarod42 8/3/2023
#include "B.hpp"在 A.hpp 中不需要(并删除循环依赖问题)。
1赞 tbxfreeware 8/4/2023
旁注:每次我看到枚举常量 和 时,我都无法从脑海中弄清楚它们的基础值分别是 和 !不。。。。当然,这对您的程序无关紧要;它不会以任何方式改变其功能。onetwoint01

答:

0赞 Aconcagua 8/4/2023 #1

在您的情况下,主要问题是循环包含!

#include "A.hpp"当然,挑衅是将那个内容包含到当前文件中,然后包含,最后又是另一个时间——然后生成的代码如下所示:B.hppA.hpp

ifndef A_HPP
#define A_HPP

ifndef B_HPP
#define B_HPP

ifndef A_HPP   // but it IS defined already, see above!!!
#define A_HPP

// definition of A,
// but NOT active!

#endif

// definition of B, NOT seeing A, as not active

#endif

// active definition of A

#endif

你需要打破循环包括! 确实依赖于 ,因为您依赖于无法预先声明的嵌套类型(我假设您不想更改...),因此该语言不支持该类型(不幸的是)。另一方面,你不需要在里面预先声明——你有包含,不是吗(好吧,到目前为止还没有工作,但我们会修复......B.hppA.hppAB.hpp

A.hpp但是,只需预先声明即可(只要您仅在 中访问成员),因此您可以 - 并且需要 - 放弃包含 .现在包括两者,并导致:Bstd::vectorA.cppB.hppA.hppB.hpp

ifndef A_HPP
#define A_HPP

// definition of A

#endif

ifndef B_HPP
#define B_HPP

ifndef A_HPP   // now again defined already
#define A_HPP

// definition of A, not active again, but this time
// it doesn't matter as it's already there above

#endif

// definition of B now seeing A
// (not from its own include but the previous one)

#endif