10

Possible Duplicate:
What's the most reliable way to prohibit a copy constructor in C++?

Suppose I want to make a class non-copyable and want to prohibit copy constructor and assignment operator. I make them private and leave unimplemented:

class Class {
//useful stuff, then
private:
    Class( const Class& ); //not implemented anywhere
    void operator=( const Class& ); //not implemented anywhere
};

this way if any of them is accidentially called from within friends or the same class I get a link-time error.

Now what if a user implements them? I mean there's no implementation, so anyone can add his own:

Class::Class( const Class& )
{
    //whatever they want
}

Of course I could have created my own implementation and add an assertion there, but that would delay unintended calls detection until the program is run.

Is there a way to prevent implementing such method by a user and still have compile-time detection of unintended calls to them?

Community
  • 1
  • 1
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 3
    If any client does this, lynch him. Interesting question nonetheless. – Xeo Apr 26 '11 at 06:48
  • 10
    Assuming the class doesn't have a really common name, it would be unlikely that a user would do this by accident. Trying to protect your code against users who are deliberately trying to circumvent your protections seems kinda pointless. – hammar Apr 26 '11 at 06:54
  • What is the point in doing this ? I mean, if you believe in idiotic clients, this should be the least of your concerns. – Alexandre C. Apr 26 '11 at 07:10
  • If you are not willing to ignore the possibility of friend classes and rogue users implemented what should not be implemented then you will have switch languages, to, e.g., Ada. There is no way to guard against that, AFAIK, in C++. – wilx Apr 26 '11 at 07:33

5 Answers5

8

There is no problem here.

The client can provide implementations of those methods a much as they like, but the compiler will still complain because they're private.

Now, can you prevent someone hacking your header file, changing them to public and linking their own implementations?

Yes, provide your own implementations that throw exceptions, your hypothetical hacker will get a link error when they try to build.

In the normal course of events this doesn't slow anything down, as the compiler will never try to call those methods, and code that tries will be told

. . . cannot access private member declared in class . . .

In the case some "clever" gobshite tries, then yes the assertions will be delayed, but mate, that's not your problem, you can't protect every idiot in the world from shooting them selves in the foot.

+1 BTW, interesting question :)

. . . as pointed out by Xeo, the above only works for non templated classes

Binary Worrier
  • 50,774
  • 20
  • 136
  • 184
  • Well, assume the class is a template class (aka needs to be header-only) and has some `friend`s (which the client may derive from), how does your solution look like now? ;) – Xeo Apr 26 '11 at 07:06
  • @Xeo: Bugger. Hadn't though of templates. It's going on 10 years since I used C++ on a daily basis, I find as each year passes my C++Fu decreases :( – Binary Worrier Apr 26 '11 at 07:30
  • @Xeo: friends are assumed to know what they're doing. If *you* can't figure out how to correctly implement copy, but they manage it, and they know what they're doing, what's the problem? ;-) Saying, "but my friends can implement it, how do I stop that" is like saying, "but I can implement it, how do I stop myself?". In C++03 you can't, in C++0x there's `=delete`. – Steve Jessop Apr 26 '11 at 09:14
  • @Steve: Well, certain friends only *think* they know what they're doing. Inserting an eel in a place where the sun doesn't shine for example... (yes, there was such an incident, with a death). – Xeo Apr 26 '11 at 09:17
  • 1
    @Xeo: sure, but I only *think* I know what I'm doing. The point is, `friend` isn't normally used to open up a class to third-parties, it's used within a group of related classes and functions. When you use `friend` to open your class to third-parties, that means you trust them with its private functions, including this one. So the problem becomes, "why did I trust this untrustworthy person", which isn't really solvable in code... – Steve Jessop Apr 26 '11 at 09:22
8

In C++0x there is the new delete keyword, that does just this

What's the most reliable way to prohibit a copy constructor in C++?

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
2

Well the solution is like it is usually done in practice - use special non-copyable base class (e.g. boost::noncopyable or your own class). E.g.

class noncopyable
{
    // private
    noncopyable( const noncopyable& ); // not implemented
    noncopyable& operator=( const noncopyable& ); // not implemented

    // no friends, etc
};

Then somewhere

class A: noncopyable
{
// Anything ...
};

Obviously since there is no friends of noncopyable its copy constuctor and assignment operator is always private for everyone so it doesn't matter if it is implemented or not (compiler denies using them anyway).

Serge Dundich
  • 4,221
  • 2
  • 21
  • 16
  • 1
    This doesn't stop someone implementing the copy ctor and assignment in the derived class. They just have to implement it so that it doesn't use the same functions from the `noncopyable` base. So agreed, this is how it's often done in practice, but it doesn't address sharptooth's issue. – Steve Jessop Apr 26 '11 at 09:18
  • @Steve Jessop: If someone implements explicit copy constructor and/or assignment operator in derived class then he/she assumes that it is exactly the way this derived class must be copied/assigned. So non-copyable class is obviously designed to prevent using illegal implicit copy constructor/assignment operator. Nothing in the world can prevent writing illegal explicit copy constructor or assignment operator. – Serge Dundich Apr 26 '11 at 09:42
1

A bit of a non-answer to the question, but perhaps a different approach, depending a lot on what you're trying to achieve.

On the face of it, it sounds like you want compile time detection whilst you're developing the library in order to speed up detection and avoid relying on runtime testing identifying the issue.

If this is the case, can you not solve your problem by having two builds?

  • Build One (internal build): which builds the library and doesn't link in the copy constructor functions.

  • Build Two (client build): which links in the copy construction logic with asserts (from a different implementation file), so that there's runtime protection & the client can't provide their own implementation.

forsvarir
  • 10,749
  • 6
  • 46
  • 77
-1

WHat you want to do is called MUTUAL exclusion.... the best way to do what you want is... MAKE ANOTHER CLASS THAT IMPLEMENTS THERE FUNCTIONS>>>>

and make an object of that class in your class.....that way you can access the function BUT NO ONE CAN else can really get into them since they dont exist in the class.... :) hope this answers your question

Izac Mac
  • 491
  • 3
  • 20