Interfaces, restricting access

C

Christopher

I am surprised this hasn't come up for me more in the past, but the
situation is:

I need to have an interface that is usable for all
I need to have an interface that is only usable for some

I do not really know of a good way to achieve this. If I use friend
functions, I can no longer make methods virtual, right?

Example:

I am making a texture class for my graphics library

The only thing the application should have access to is a string
filename to create it with, perhaps dimensions, and a few other
things.

However, some classes inside the engine, such as say the renderer
should have access to the hardware level texture resource, which is in
this case a pointer to a struct from a 3rd party library. So, I need
accessors for my renderer to use, but do not want them to be available
to the application. Both are using the same class.
 
S

Salt_Peter

I am surprised this hasn't come up for me more in the past, but the
situation is:

I need to have an interface that is usable for all
I need to have an interface that is only usable for some

I do not really know of a good way to achieve this. If I use friend
functions, I can no longer make methods virtual, right?

Example:

I am making a texture class for my graphics library

The only thing the application should have access to is a string
filename to create it with, perhaps dimensions, and a few other
things.

However, some classes inside the engine, such as say the renderer
should have access to the hardware level texture resource, which is in
this case a pointer to a struct from a 3rd party library. So, I need
accessors for my renderer to use, but do not want them to be available
to the application. Both are using the same class.

Provide access(...) using interfaces only

We need a dummy Resource,
a core Texture type (string member and a pointer)
application needs an interface: IApplication
renderer needs another interface: IRenderer
type Texture overloads access(...) based on interface type.

#include <iostream>

struct Resource
{
};

struct IApplication
{
virtual void set(const std::string&) = 0;
};

struct IRenderer
{
virtual void set(Resource* p) = 0;
};

class Texture
{
const std::string m_s;
Resource* p_res;
public:
Texture(std::string s) : m_s(s), p_res(0) { }
void access(IApplication& ia) const
{
ia.set(m_s);
}
void access(IRenderer& ir) const
{
ir.set(p_res);
}
void setp(Resource* p)
{
p_res = p;
}
};

class Application : public IApplication
{
std::string m_s;
public:
void set(const std::string& r_s)
{
m_s = r_s;
}
void display() const
{
std::cout << m_s << std::endl;
}
};

class Renderer : public IRenderer
{
Resource* p_res;
public:
void set(Resource* p)
{
p_res = p;
}
void display() const
{
std::cout << p_res << std::endl;
}
};

int main()
{
// setup an environment
Resource res;
Texture tex("some string");
tex.setp( &res );

// application's access
Application app;
tex.access( app );
app.display();

// renderer's access
Renderer rend;
tex.access( rend );
rend.display();
}

/*
some string
0x7fff4c23687f
*/
 
C

Christopher

Provide access(...) using interfaces only

We need a dummy Resource,
a core Texture type (string member and a pointer)
application needs an interface: IApplication
renderer needs another interface: IRenderer
type Texture overloads access(...) based on interface type.

#include <iostream>

struct Resource
{

};

struct IApplication
{
  virtual void set(const std::string&) = 0;

};

struct IRenderer
{
  virtual void set(Resource* p) = 0;

};

class Texture
{
  const std::string m_s;
  Resource* p_res;
public:
  Texture(std::string s) : m_s(s), p_res(0) { }
  void access(IApplication& ia) const
  {
    ia.set(m_s);
  }
  void access(IRenderer& ir) const
  {
    ir.set(p_res);
  }
  void setp(Resource* p)
  {
    p_res = p;
  }

};

class Application : public IApplication
{
  std::string m_s;
public:
  void set(const std::string& r_s)
  {
    m_s = r_s;
  }
  void display() const
  {
    std::cout << m_s << std::endl;
  }

};

class Renderer : public IRenderer
{
  Resource* p_res;
public:
  void set(Resource* p)
  {
    p_res = p;
  }
  void display() const
  {
    std::cout << p_res << std::endl;
  }

};

int main()
{
  // setup an environment
  Resource res;
  Texture tex("some string");
  tex.setp( &res );

  // application's access
  Application app;
  tex.access( app );
  app.display();

  // renderer's access
  Renderer rend;
  tex.access( rend );
  rend.display();

}

/*
some string
0x7fff4c23687f
*/- Hide quoted text -

- Show quoted text -


Not sure I follow.
You now have an Application class that is a Texture or at least has
methods and data specific to the texture.
Maybe I am just getting confused on names and made it too specific.


class A
{
public:

// Can be called by anyone
virtual void Method1();
virtual void Method2();
virtual void Method3();

// Can only be called by a class C
virtual void Method4();
virtual void Method5();

private:

// All 5 methods manipulate this data a differant way
int * m_data;
};

class B
{
public:
Foo()
{
A * a = new A();
a->Method1();

// Not allowed!
a->Method5();
}
};


class C
{
Bar()
{
A * a = new A();
a->Method1();

// Is OK
a->Method5();
}
};
 
E

Erik Wikström

I am surprised this hasn't come up for me more in the past, but the
situation is:

I need to have an interface that is usable for all
I need to have an interface that is only usable for some

I do not really know of a good way to achieve this. If I use friend
functions, I can no longer make methods virtual, right?

Not sure exactly what you mean by that, a friend function/class can call
a virtual function (as shown in this, somewhat contrived, example):

#include <iostream>

class PubInterface
{
public:
virtual void PubFunc() = 0;
};

class PrivInterface
{
virtual void PrivFunc() = 0;
friend void doIt(PubInterface&);
};

void doIt(PubInterface& i)
{
i.PubFunc();

PrivInterface* pi = dynamic_cast<PrivInterface*>(&i);
if (pi != 0)
pi->PrivFunc();
}

class Impl1 : public PubInterface
{
public:
void PubFunc()
{
std::cout << "PubFunc()\n";
}
};

class Impl2 : public PubInterface, public PrivInterface
{
void PrivFunc()
{
std::cout << "PrivFunc()\n";
}

public:
void PubFunc()
{
std::cout << "PubFunc()\n";
}
};


int main()
{
Impl1 i1;
Impl2 i2;

doIt(i1);
doIt(i2);

return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top