使用C ++ for Windows进行编程,但这种情况可能会出现在任何地方。这是我的问题的简化版本,以保持问题的可管理性,所以不要过于关注细节:)
我有一个类class Window
,其中包含一个Windows HWND
数据项。我想完全封装HWND
,以便类的用户必须通过类来对该窗口执行任何操作,因此它存储在私有成员变量中。我不想为它提供任何公开的“getter”,因为这会破坏允许用户绕过我的课程的封装。
现在我想创建一个类class Direct3d11
来封装一些directx api。为了创建这个类的实例,它需要一个窗口的HWND,所以我在它的构造函数中传递了一个Window
对象。
class Direct3D11
{
public:
Direct3D11(const Window& window);
};
在构造函数内部,它可以访问window对象,但是它需要包含在其中的HWND,以便能够物理地创建Direct3D11类将管理的windows对象,但是它无法获取该信息
我可以添加一个私有的getter函数来获取Window类的HWND,然后让Direct3D11类成为Window的友元类,以便调用它来调用函数。
然而,这似乎并不是非常优雅,因为类Window对于Direct3D11类没有任何了解。
我错过了更好的方法来实现这一目标吗?朋友课程没有吸引力,拥有公共吸气功能也不具吸引力。
答案 0 :(得分:3)
您可以在Direct3D11
内创建Window
课程,因为Windows
拥有HWND
。
这些方面的东西:
class Window
{
HWND hwnd;
Direct3D11 d;
public:
Window() : d(hwnd) {}
Direct3D11& getDirect3D()
{
return d;
}
}
答案 1 :(得分:1)
你可能在Window上有一个名为Execute的函数。它将使用带有HWND占位符的std :: function作为参数。然后,Window将以HWND作为唯一参数调用该函数。
这需要c ++ 11,但代码类似于:
#include <functional>
#include <iostream>
struct Foo {
explicit Foo(int num) : num_(num) {}
template<typename T>
void execute(std::function<T> f) const { f(num_); }
private:
int num_;
};
struct Bar{
void print_nums(int i,int j)
{
std::cout << "i:" << i << ", " << "j:" << j << std::endl;
}
};
int main()
{
Foo o(42);
Bar b;
//the function we want to execute requires an int
//that Foo knows about
typedef void myFunction(int);
// store the result of a call to std::bind
std::function<myFunction> display_1337_first = std::bind(&Bar::print_nums, b,1337, std::placeholders::_1);
std::function<myFunction> display_1337_last = std::bind(&Bar::print_nums, b, std::placeholders::_1, 1337);
o.execute<myFunction>(display_1337_first);
o.execute<myFunction>(display_1337_last);
return 0;
}
//output:
//i:1337, j:42
//i:42, j:1337
答案 2 :(得分:1)
在你的情况下,我建议为HWND
提供一个getter,因为你可能会更频繁地需要它。提供getter并不意味着你承担了Window类的责任,它仍然负责窗口的生命周期。您只需使其更易于使用,并且更容易在用例中划分代码。
那就是说,这是一个更通用的方法,你可以尝试:
class Window;
class Direct3D {
public:
void apply(Window &window, HWND hWnd);
};
class Window {
public:
void accept(Direct3D &direct3d) {
direct3d.apply(*this, this->m_hWnd);
}
};
答案 3 :(得分:1)
如果您愿意使用friend关键字,您可以确保窗口不知道需要hwnd的类。只需创建为您处理操作的类(该窗口和DirectX继承)。这使您可以解决DirectX的问题,并在下次出现时解决它。
Side Rant: 朋友不是一个四个字母的单词。朋友,如果合理使用,实际上是为C ++的访问控制添加渐变的好方法(公共,朋友(在受保护时),受保护,朋友(在私人时),私人)。
#include <iostream>
class HwndOwner;
class HwndWanter
{
protected:
HwndWanter(){}
int getHwndFromOwner(HwndOwner & owner);
};
class HwndOwner
{
protected:
HwndOwner() : hwnd(42){}
private:
friend class HwndWanter;
int getHwnd()
{
return hwnd;
}
int hwnd;
};
class Window : public HwndOwner
{
//This is not the class you are looking for...
};
class Direct3D : private HwndWanter
{
public:
Direct3D(HwndOwner & owner)
: HwndWanter()
{
std::cout << getHwndFromOwner(owner) << std::endl;
}
};
int HwndWanter::getHwndFromOwner(HwndOwner & owner)
{
return owner.getHwnd();
}
int main()
{
Window window;
Direct3D hwndWanter(window);
}
输出:
42