Click here to Skip to main content
15,867,330 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I am updating a big C++ based application from Visual Studio 2003 to 2010. Also we're running the updated version on Windows 2008 Server. The original project was built using the XML C++ library Xerces.

First they extend HandlerBase from a Xerces class, next they disable the assignment operator and the disable copy constructor:


C++
class XMLResponseBase : public HandlerBase 
{
public:
explicit XMLResponseBase(const char *lpszXML, size_t sizeXML, const char *funcao);
//...
private:
	XMLResponseBase(const XMLResponseBase &) {;}
	XMLResponseBase &operator=(const XMLResponseBase &) {;}
};


Next, XMLResponseBase is extended and the copy constructor and assignment operator are disabled:

C++
class XMLLegadoResponse : public XMLResponseBase
{
public:
	explicit XMLLegadoResponse(const char *lpszXML, size_t sizeXML, const char *funcao);

private:
	XMLLegadoResponse(const XMLLegadoResponse &origial) : XMLResponseBase(NULL, 0, "") {;}
	XMLLegadoResponse &operator=(const XMLLegadoResponse &origial) {;}
};



I supposed that: if by making the copy constructor and assignment private it would not be possible to call them in code. But something like this is later done:


C++
const XMLLegadoResponse& xmlResponse = servidorLegado.ListaAssinantesHSM(documento, pessoaJuridicaHsm);


This method ListaAssinantesHSM return a const reference to XMLLegadoResponse, so far I am ok to it.

But later they try to create a reference to this object this in a way that is puzzling me:

C++
const XMLLegadoResponse &xmlResponse(servidorLegado.ListaAssinantesHSM(documento,pessoaJuridicaHsm));


Ok if the method returns a const reference to the an already instantiated object, thus:

- The assignment operator can be called because I am returning a const reference, right?
- Also, can I assign this const referenced object to instantiate a copy of the object? If Yes, how can I do that if the copy constructor is disabled ?

Sorry if this is a very simple question or if I ask something too obvious.

Thanks
Posted

In both of your examples the assignment operator is not used; instead a const reference is initialized. And that is perfectly legal even if the assignment operator of the class in question has been made inaccessible to the public.

You can only use that const reference to instantiate another object of that type if a corresponding copy constructor is accessible. And you can only assign to a new object if the assignment operator is accessible. So on both accounts in your case a NO.

And don't worry, this is not a simple question at all. C++ initialization and operator overloading is a complex subject.
 
Share this answer
 
Comments
zlogdan 10-Jun-13 17:14pm    
@nv3 , Thanks! I understood you well, just want to make something else clear. You said that it is not possible to instantiate an object if the copy constructor is not accessible, thus in the above cases ( as the copy constructor is made private) there is an implementation error, right ? The compiler should have raised an error ? I am actually facing a trouble at this part of the code someone else wrote like 8 years ago. Still polishing operator overloading skills. Thanks!
Philippe Mori 10-Jun-13 18:44pm    
A reference is very similar to a pointer... You can always copy a pointer and it is the same for a reference. When the copy constructor or the assignment operator is private, it is the object itself that cannot be copied not reference to it.
Espen Harlinn 10-Jun-13 17:46pm    
Well answered :-D
zlogdan 11-Jun-13 8:54am    
Thank you all!
H.Brydon 17-Jun-13 0:00am    
I think there are also some errors/omissions in your analysis; see solution #2.
I've read your question several times and Solution #1 trying to understand the problem better, and I'm still not sure I have my head around it. You say that the copy constructor and assignment=() are disabled but they are not. In the code you provide above, they are implemented as empty methods but are callable and will not work correctly if called.

Note the important difference between the lines:
C++
XMLLegadoResponse &operator=(const XMLLegadoResponse &origial) {;}
XMLLegadoResponse &operator=(const XMLLegadoResponse &origial);

You want the APIs disabled, so you want the latter.

You also have not disabled the default constructor. You probably want to do that.

I think you want to do the following in the original code:
C++
class XMLResponseBase : public HandlerBase
{
public:
explicit XMLResponseBase(const char *lpszXML, size_t sizeXML, const char *funcao);
//...
private:
    XMLResponseBase();  // no implementation
    XMLResponseBase(const XMLResponseBase &);  // no implementation
    XMLResponseBase &operator=(const XMLResponseBase &);  // no implementation
};

And your derived class should be similar to:
C++
class XMLLegadoResponse : public XMLResponseBase
{
public:
    explicit XMLLegadoResponse(const char *lpszXML, size_t sizeXML, const char *funcao);

private:
    XMLLegadoResponse();  // no implementation
    XMLLegadoResponse(const XMLLegadoResponse &); // no implementation
    XMLLegadoResponse &operator=(const XMLLegadoResponse &); // no implementation
};
 
Share this answer
 
v3
Comments
nv3 17-Jun-13 2:54am    
Good points, Harvey. My 5.
zlogdan 17-Jun-13 9:00am    
Many thanks H.Brydon. I am updating the system (from lame VS 2003 ) to VS 2010. So I am daily puzzled with things that seem quite weird under comparison to C++ standards. I must admit that I have never used this kind of protection in my own code, I just have read it in books/tutorials. My original question was why someone was trying to use the code I posted, instead of doing it properly as you did above. And in the code, they ( people that wrote the code before ) wrote initialization like: const XMLLegadoResponse &xmlResponse(servidorLegado.ListaAssinantesHSM(documento,pessoaJuridicaHsm)); Where ListaAssinantesHSM returns a const reference to a XMLLegadoResponse object. I also had seen the usage of the assignment operator like in
const XMLLegadoResponse& xmlResponse = servidorLegado.ListaAssinantesHSM(documento, pessoaJuridicaHsm); First, I try to change the least possible in legated code, because If it does not work, they usually blame me :-) Always hear "so-called experts" saying "why are trying to convert it to a newer compiler?" and usually I have seen that VS 2003 is a quite permissive compiler in terms of absurdity and lack of compliance and usually my bosses hardly know what an ISO standard is. I had one boss that told me he, 3 years ago, he was against things that were not really C++ like "std::vector or std::string". Second, I read my C++ books several times and I was not sure what they original coders wanted. I thought it was something simple and I was missing the point.
@nv3 If you don't mind I would like to change the accepted H.Brydon's solution instead, let me know if you are ok to it.
H.Brydon 17-Jun-13 11:09am    
I have upgraded a codebase of ~10 million lines of code through several Visual Studio compiler versions, and I take the opposite approach. Regardless of what you might think about Microsoft or their compilers, each version of the compiler is better than the previous, and upgrading compilers brings out warnings and errors that make me wonder how in the world some of the code could possibly work. Upgrading is a lot of work but it is good work.

I also set my compile settings to /W4, and pay attention to all of the warnings. This has produced much better code with fewer bugs.
zlogdan 17-Jun-13 11:39am    
@H.Brydon. I completely agree with everything you said, that is my desired approach. But please bear in mind that down here in Brazil one is always easy to meet a boss or co-workers with high status that yours that are unwilling to accept they are outdated. After being terribly bashed for stimulating them to take modern approachs, I have had always got replies like "Why are you upgrading the compiler? Why you are changing this line ?". In the end I gave up. Still, I update every non-compliant I find, removing the warnings even. But at this present time I was not aware of what the developers meant. My experience always tells me to don't argue with the moto "They did it before, it worked, they cannot be wrong". It is strange that at my previous work we had to port our code to Linux and once lots of innacuricies were pointed by the compiler output I had to just say "this gcc compiler is crazy" instead of "what would you expect from converting from a real lame compiler to a decent one"? I had a coworker who did not know what a class was exactly, he just worked his way out copying code from the web. He was older than I at the job, and he knew the product quite well. Everytime I told him I was upgrading the code to better compiler he said "Why? This new compiler is bad! Use VS 2003". I know I should have consistently told him he was wrong, but I lowered my head. Stubborn folks are never convinced to be wrong.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900