问题描述:

I wish to compile part of my code as a static library to include in other project. Of course I'll have to distribute the compiled library and an header file containing the class declaration and the public members, but I don't know if it's possible to move all private members and declarations to a place different than the header file.

Example:

In the project.h file:

class MyClass

{

public:

MyClass();

void Give_me_an_input(int);

int Get_your_output();

private:

int a, b;

int MySecretAlgorithm();

};

In the .cpp file:

MyClass::MyClass()

{

a = 1;

b = 0;

}

void MyClass::Give_me_an_input(int c)

{

b = c;

}

int MyClass::Get_your_output()

{

return MySecretAlgorithm();

}

int MyClass::MySecretAlgorithm()

{

return (a + b);

}

Is there a way to move all private members int a, b; and int MySecretAlgorithm(); to a place different than the header file?

网友答案:

The pointer to implementation idiom can be used in such a scenario, commonly referred to as pimpl. The basic idea is to take the implementation details out of the declaration and simply have an opaque pointer to the implementation details.

std::unique_ptr is used in the the following example; but you could of course just use normal pointers.

// my_class declaration unit.
class my_class {
private:
   class impl;
   unique_ptr<impl> pimpl;

public:

};

// my_class implementation unit
class my_class::impl {
   int whatever;
   int whenever;
};

my_class::my_class(): pimpl( new impl )
{
}
网友答案:

Over the years I've seen some hacks to do this, but I don't think they are worth it. If your library is reasonably 'chunky' (ie: no method is being called a billion times a microsecond); and you can re-write chunks of your code...

You might consider making all the public stuff an abstract class (all virtual = 0) and then deriving your concrete classes from it.

Down sides of this: - All your public calls become virtual (some optimizations can bypass this, but not often). - You can't 'new up' your classes anymore, you'll need to implement a factory pattern.

The problem with any of the other hacks I'm familiar with is that they basically declare the methods in one set of headers, and then redeclare the same things with the 'real' implementation in private headers - depending on the linker to match up the names. A couple problems here are:

  • Maintaining this mess sucks. You can't use an #ifdef because it sounds like you want to physically hide your implementation. So you have dual maintaining, or a build step that generates your public headers.

  • Can only be used via pointer. You have to play games making constructors private and still have a factory because the compiler won't generate structs of the right size if you let the client gen it by value (or even with new).

  • Finally, I once saw a hack where the programmer tried to declare a byte array in the private area of the 'public' class so that the client code could still declare by value or 'new' it themselves. This suffers all the previous problems, plus you probably don't want to have to 'know' the size of the structs since they depend on packing and alignment. Your 'build step' would more or less have to have a runtime component that used sizeof() - and now you have a versioning problem if you want to change the size of the struct/class.

相关阅读:
Top