Interfaces and polymorphism producing a compiler warning

F

franko.man

Disclaimer: I am a university student in a not-directly programming
related field, although I want to go into programming, so I have not
yet taken any real formal programming courses or training. If my
question seems simple or odd please forgive me! :)

I have been trying to expand my C++ knowledge by wrapping a C++/CLI
(Microsoft extension) class so that it can be used in unmanaged C++.
To my understanding, the only way to accomplish this is to create a
library containing an unmanaged interface to mixed wrapper classes
(i.e. classes containing gcroot<T^> items from vcclr.h). I have been
able to do this without problems; however, while attempting to make
the interface and wrapper classes polymorphic I am receiving compiler
warning that bug me.

Below is a minimal trivial example that illustrates the problem and
contains no C++/CLI (as that would be off-topic in this newsgroup).
The code has been compiled and run in Visual Studio 2008 Express
V9.0.30729.1 under Windows XP. The only warning is “warning C4250:
'Derived' : inherits 'Base::Base::GetShort' via dominance”, which can
be solved by including the GetShort() definition that is currently
commented out in the Derived class -- although this does not change
the behaviour of the code. I am hoping that there is a better way to
accomplish this so that I do not have to explicitly forward calls from
the derived functions to the base functions (as with non-trivial code
this would be very repetitive and prone to error). Any additional
nitpicks on my code would also be appreciated!

Thanks in advance,
Franko

class IBase
{
public:
virtual ~IBase() { }
virtual short GetShort() const = 0;
};

class IDerived : public virtual IBase
{
public:
virtual int GetInt() const = 0;
};

class Base : public virtual IBase
{
public:
Base(short s) : m_s(s) { }
virtual short GetShort() const
{
return m_s;
}
protected:
short m_s;
};

class Derived : public virtual IDerived, private virtual Base
{
public:
Derived(int i, short s) : Base(s), m_i(i) { }
virtual int GetInt() const
{
return m_i;
}
//virtual short GetShort() const
//{
// return Base::GetShort();
//}
// warning C4250: 'Derived' : inherits 'Base::Base::GetShort' via
dominance
private:
int m_i;
};

IDerived* CreateDerived(int i, short s)
{
return new Derived(i, s);
}

#include <iostream>
using std::eek:stream;
using std::cout;
using std::endl;

ostream& operator<<(ostream& os, IBase const * const pBase)
{
return os << pBase->GetShort() << endl;
}

ostream& operator<<(ostream& os, IDerived const * const pDerived)
{
IBase const * const pBase = pDerived;
return os << pDerived->GetInt() << endl << pBase;
}

int main(int argc, char** argv)
{
IDerived* pDerived = CreateDerived(5, 2);
IBase* pBase = pDerived;

cout << pDerived << endl;
cout << pBase << endl;

delete pDerived; // or delete pBase

system("PAUSE");
}
 
T

Triple-DES

On 14 Apr, 03:33, (e-mail address removed) wrote:

....
Below is a minimal trivial example that illustrates the problem and
contains no C++/CLI (as that would be off-topic in this newsgroup).
....

Any additional
nitpicks on my code would also be appreciated!
Okay,
....

class Base : public virtual IBase
{
public:
Base(short s) : m_s(s) { }
virtual short GetShort() const
{
return m_s;
}
protected:
short m_s;

};

Consider making this single-argument constructor explicit, unless
there is a good reason not to. Allowing implicit conversion from short
to Base may have surprising results.

Any reason in particular m_s is protected and not private?

....
ostream& operator<<(ostream& os, IBase const * const pBase)
....
The latter const serves no useful purpose here.
ostream& operator<<(ostream& os, IDerived const * const pDerived)
{
IBase const * const pBase = pDerived;
return os << pDerived->GetInt() << endl << pBase;
}

Same with the const here. Could also be written as:
return os << pDerived ->GetInt() << endl
<< static_cast<const IBase*>(pDerived);

essentially replacing the automatic object with a temporary (for
better or worse).
int main(int argc, char** argv)
{ ....
system("PAUSE");
}

You are missing a declaration for the system function. #include
<cstdlib> or <stdlib.h>
 
F

franko.man

The statement in the warning is true. I have no idea why some compiler
writer thought you needed to be told what you'd done. Dominance is
intended for exactly this kind of situation.

Thanks for the clarification,
Franko
 
F

franko.man

[snip]
class Base : public virtual IBase
{
public:
Base(short s) : m_s(s) { }
virtual short GetShort() const
{
return m_s;
}
protected:
short m_s;

Consider making this single-argument constructor explicit, unless
there is a good reason not to. Allowing implicit conversion from short
to Base may have surprising results.

Any reason in particular m_s is protected and not private?

For this trivial example m_s could be private instead of protected; I
was just mimicking my actual code where protected members are used.
Basically, my code is for communication that allows either local or
remote (using Windows Communication Foundation) connections to a
socket or a serial port. As I prefer writing things such as "if
( m_Connected )" to "if ( IsConnected() )" in derived classes, I went
with protected members as I believe that is what they are meant for.
Also, this code is meant to be added as a static library to other
projects with a header containing only the interface classes (to allow
the C++/CLI code to be used in unmanaged C++). This means that only I
have access to the concrete classes and I can't think of any drawbacks
to using protected members in this case.
...
The latter const serves no useful purpose here.


Same with the const here. Could also be written as:
return os << pDerived ->GetInt() << endl
<< static_cast<const IBase*>(pDerived);

essentially replacing the automatic object with a temporary (for
better or worse).

Arguably the former const serves no purpose in this trivial example as
there are no non-const member functions that could be called. Even if
there were non-const member functions, I would say that both const
still serve no real purpose as I wouldn't /knowingly/ try to call any
non-const member functions. However, in the event that I /accidently/
do something that I don't want, the compiler will let me know so that
I can fix it. Additionally, to my knowledge the const qualifier
doesn't affect the run-time of the program, so I don't really see a
reason to not include it. It would help prevent horrible mistakes
such as:

ostream& operator<<(ostream& os, IDerived const * pDerived)
{
pDerived = CreateDerived(pDerived->GetInt(), pDerived->GetShort
());
return os << pDerived->GetInt() << endl << static_cast<IBase
const * const>(pDerived);
} // same functionality but now there's a leak!

Is there a reason you are suggesting to remove the second const that I
am unaware of?
You are missing a declaration for the system function. #include
<cstdlib> or <stdlib.h>

Ah, I didn't even know that -- silly VS compiler automatically does it
for me!

Thanks,
Franko
 

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,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top