|
-
February 25th, 2008, 08:36 AM
#1
Compiler Warning C4373 about virtual methods
Hello everyone,
The following code will result in C4373 warning message. In MSDN,
http://msdn2.microsoft.com/en-us/library/bb384874.aspx
I do not quite understand the following statement,
1. What means "bind"? Putting function pointer into the vtable of the related class?
2. const is ignored in derived class?
--------------------
This means the compiler must bind a function reference to the method in either the base or derived class.
Versions of the compiler prior to Visual C++ 2008 bind the function to the method in the base class, then issue a warning message. Subsequent versions of the compiler ignore the const or volatile qualifier, bind the function to the method in the derived class, then issue warning C4373. This latter behavior complies with the C++ standard.
--------------------
Code:
class Base {
public:
virtual int goo (const int input) {return 200;}
};
class Derived : public Base {
public:
virtual int goo (int input) {return 200;} // change const property of input parameter
};
int main()
{
Derived d;
const int a = 1000;
d.goo (a); // pass const to non-const
return 0;
}
Compile warning message,
1>d:\visual studio 2008\projects\test_overriding1\test_overriding1\main.cpp(8) : warning C4373: 'Derived::goo': virtual function overrides 'Base::goo', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers
1> d:\visual studio 2008\projects\test_overriding1\test_overriding1\main.cpp(3) : see declaration of 'Base::goo'
regards,
George
-
February 25th, 2008, 10:34 AM
#2
Re: Compiler Warning C4373 about virtual methods
Hey George,
1. Yes, in this context, "binding to a class" means associating the vTable pointer to the corresponding function in that class.
2. Are you asking if the constness of a is lost in Derived::goo()? Yes, that is correct. However, since you are passing a by value (you can't pass a by non-const reference), whatever changes you make to the parameter inside the function will not affect a. Incidentally, MinGW 3.7 does not give any warning and successfully binds the function to the derived class method. Wonder why Microsoft took so long to realise this?
-
February 25th, 2008, 10:56 AM
#3
Re: Compiler Warning C4373 about virtual methods
On a related note, I just encountered the old "class has virtual functions but non-virtual destructor" warning.
I know I've encountered and dealt with this before, but the details are slipping my mind at the moment.
The base class is pure-virtual, existing only so that I can use common accessor functions on several derived classes. No destructors are explicitly defined for any of them; they contain only POD and some STL containers (which have their own destructors), so I assumed the default destructor would be good enough.
What do I need to do to make the warning go away? (Besides just disabling it, of course.)
-
February 25th, 2008, 11:17 AM
#4
Re: Compiler Warning C4373 about virtual methods
Hey Lindley,
Could you post some working code illustrating the problem?
-
February 25th, 2008, 11:25 AM
#5
Re: Compiler Warning C4373 about virtual methods
Not easily. However, I can post simplified class declarations. Since this isn't exactly an obscure error, that should be enough to tell me what I'm doing wrong. Google turned up a number of hits on the message, but none of the explanations were completely clear.
Code:
class GraphPart
{
public:
virtual void setField(std::string fieldname, std::string value)=0;
virtual bool cmpField(std::string fieldname, std::string value) const=0;
virtual const char* getField(std::string fieldname) const=0;
};
class GraphNode: public GraphPart
{
public:
// data is a mix of non-pointer primitives and STL containers, nothing else
void setField(std::string fieldname, std::string value);
bool cmpField(std::string fieldname, std::string value) const;
const char* getField(std::string fieldname) const;
};
class GraphEdge: public GraphPart
{
public:
// data is non-pointer primitives
void setField(std::string fieldname, std::string value);
bool cmpField(std::string fieldname, std::string value) const;
const char* getField(std::string fieldname) const;
};
Before anyone mentions it, the reasoning for not using const string references in the parameters is so that const char*-type strings, including literals, may be passed.
-
February 25th, 2008, 11:30 AM
#6
Re: Compiler Warning C4373 about virtual methods
Before anyone mentions it, the reasoning for not using const string references in the parameters is so that const char*-type strings, including literals, may be passed.
Eh, but temporaries and literals can be bound to const references.
EDIT:
The warning is just that you should declare the base class destructor virtual so as to avoid undefined behaviour if an object of a derived class is deleted through a pointer to the base class.
-
February 25th, 2008, 11:48 AM
#7
Re: Compiler Warning C4373 about virtual methods
I had previously tried that (the const reference thing), and got errors. Just did again and it worked. Oh well, I must have screwed something up last time.
Likewise, when I tried adding a pure virtual destructor to the base class I got undefined symbol messages....turns out that even pure virtual classes need actual destructor definitions (!?) in order to compile, even when they're virtual.
-
February 25th, 2008, 12:01 PM
#8
Re: Compiler Warning C4373 about virtual methods
Likewise, when I tried adding a pure virtual destructor to the base class I got undefined symbol messages....turns out that even pure virtual classes need actual destructor definitions (!?) in order to compile, even when they're virtual.
Yes, that is true. It sounds like you just ran into a stroke of bad luck or something, heheh.
-
February 25th, 2008, 12:07 PM
#9
Re: Compiler Warning C4373 about virtual methods
 Originally Posted by Lindley
On a related note, I just encountered the old "class has virtual functions but non-virtual destructor" warning.
I know I've encountered and dealt with this before, but the details are slipping my mind at the moment.
The base class is pure-virtual, existing only so that I can use common accessor functions on several derived classes. No destructors are explicitly defined for any of them; they contain only POD and some STL containers (which have their own destructors), so I assumed the default destructor would be good enough.
What do I need to do to make the warning go away? (Besides just disabling it, of course.)
I know that you need to make the destructor in the base class virtual. Unfortunately, I am not able to reproduce this warning with my VS 2005 compiler. What compiler are you using Lindley?
Likewise, when I tried adding a pure virtual destructor to the base class I got undefined symbol messages....turns out that even pure virtual classes need actual destructor definitions (!?) in order to compile, even when they're virtual.
Section 12.4 in the standard:
A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined.
-
February 25th, 2008, 12:13 PM
#10
Re: Compiler Warning C4373 about virtual methods
 Originally Posted by angelorohit
I know that you need to make the destructor in the base class virtual. Unfortunately, I am not able to reproduce this warning with my VS 2005 compiler. What compiler are you using Lindley?
Neither am I, even on -W4, and that was part of the problem. This came off a list of warnings generated on Linux by g++ on my code that was sent to me. I write all my code to be cross-platform.
Section 12.4 in the standard:
A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined.
If I'm reading that right----mentally substituting "must" for "shall" at the end there----that seems arbitrary, but at least it's something to work from.
-
February 25th, 2008, 12:33 PM
#11
Re: Compiler Warning C4373 about virtual methods
1) EVERY class must have a destructor implementation. It can be the "generated" destructor, or an explicitly written destructor. This may be optimized out of existance, but must initialy exist.
2) When you declare any method (including the destructor) it prevents the creation of a default implementation
3) The destructor of a base class (even if it has no members) MUST be virtual in order to funcion properly, if any of the derived classes have any data members. Since this can NOT be detected by the compiler by looking at only the base class, it generates a warning:
Consider:
Code:
class Base
{
~Base(); // NOT virtual...
}
class Derived
{
private SomeThing s;
}
B *test = new Derived();
delete test;
There is no way for the delete to invoke the (automatic) destricutor of class Derived (a virtual destructor on Base is required). Therefore D::s will never be properly destructed.
Clear?
}
Last edited by TheCPUWizard; February 25th, 2008 at 12:50 PM.
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
February 25th, 2008, 12:35 PM
#12
Re: Compiler Warning C4373 about virtual methods
Makes sense. The confusion was mainly on why a pure virtual base class would need a destructor definition, as opposed to merely a declaration that it was virtual.
-
February 26th, 2008, 02:12 AM
#13
Re: Compiler Warning C4373 about virtual methods
Hi Lindley,
I have tried to compile your code in Visual Studio 2008, no compile warning/errors.
Do you have any comments?
Why your code have something to do with my original question?
 Originally Posted by Lindley
Not easily. However, I can post simplified class declarations. Since this isn't exactly an obscure error, that should be enough to tell me what I'm doing wrong. Google turned up a number of hits on the message, but none of the explanations were completely clear.
Code:
class GraphPart
{
public:
virtual void setField(std::string fieldname, std::string value)=0;
virtual bool cmpField(std::string fieldname, std::string value) const=0;
virtual const char* getField(std::string fieldname) const=0;
};
class GraphNode: public GraphPart
{
public:
// data is a mix of non-pointer primitives and STL containers, nothing else
void setField(std::string fieldname, std::string value);
bool cmpField(std::string fieldname, std::string value) const;
const char* getField(std::string fieldname) const;
};
class GraphEdge: public GraphPart
{
public:
// data is non-pointer primitives
void setField(std::string fieldname, std::string value);
bool cmpField(std::string fieldname, std::string value) const;
const char* getField(std::string fieldname) const;
};
Before anyone mentions it, the reasoning for not using const string references in the parameters is so that const char*-type strings, including literals, may be passed.
regards,
George
-
February 26th, 2008, 02:19 AM
#14
Re: Compiler Warning C4373 about virtual methods
Hi angelorohit,
I am confused what do you mean "(you can't pass a by non-const reference)".
I have shown you the code below, we can pass non-const reference to method goo. Any comments?
Code:
class Base {
public:
virtual int goo (const int input) {return 200;}
};
class Derived : public Base {
public:
virtual int goo (int input) {return 200;} // change const property of input parameter
};
int main()
{
Derived d;
int a = 100;
int& ri = a;
d.goo (ri); // pass const to non-const
return 0;
}
 Originally Posted by angelorohit
Hey George,
1. Yes, in this context, "binding to a class" means associating the vTable pointer to the corresponding function in that class.
2. Are you asking if the constness of a is lost in Derived::goo()? Yes, that is correct. However, since you are passing a by value (you can't pass a by non-const reference), whatever changes you make to the parameter inside the function will not affect a. Incidentally, MinGW 3.7 does not give any warning and successfully binds the function to the derived class method. Wonder why Microsoft took so long to realise this?
regards,
George
-
February 26th, 2008, 02:23 AM
#15
Re: Compiler Warning C4373 about virtual methods
Thanks Lindley,
What does your term "common accessor functions" mean? I searched for wikipedia and Google, can not find the definition. :-)
 Originally Posted by Lindley
On a related note, I just encountered the old "class has virtual functions but non-virtual destructor" warning.
I know I've encountered and dealt with this before, but the details are slipping my mind at the moment.
The base class is pure-virtual, existing only so that I can use common accessor functions on several derived classes. No destructors are explicitly defined for any of them; they contain only POD and some STL containers (which have their own destructors), so I assumed the default destructor would be good enough.
What do I need to do to make the warning go away? (Besides just disabling it, of course.)
regards,
George
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|