Undefined symbol when defined outside class, works when defined inside class - c++

I'm somewhat new to C++ and am trying to understand the syntax and its behaviour. In particular, after quite a bit of googling and research, I was unable to find out why the following code won't compile:
class base {
public:
base (const int);
};
class child: base {
public:
child (const int);
};
child::child(const int num) : base(num) {}
but this will:
class base {
public:
base (const int);
};
class child : base {
public:
child (const int num) : base(num) {};
};
In the above case the linker fails with:
Undefined symbol base::base(int)
I feel like I'm making a very stupid mistake but the compiler's errors are completely unhelpful.

The compiler is telling you exactly what the problem is. You must define a constuctor for base if you invoke it, and you are invoking it from the derived class child.
Try adding this to your code:
base::base(const int num) {}
This ignores the given argument, but at least your code will compile.
I would probably remove the declaration for the base constructor and not pass any value to it from the child class unless it was actually used.
In the second case, the constructor is inline and never invoked so the compiler does not need to generate code for it, but if you try to actually construct a child object, you will get the same linker error.
The reason inline code is not generated is because you have no invoking call site. The whole purpose behind declaring code inline is so that it is inlined at the call site. Thus the compiler defers code generation for all inline code until it is actually called.

When you define the constructor within the class, the compiler doesn't actually look for the base class constructor until you try to actually instantiate a member of the class. Once you do that (via e.g. child a(5);), you will get the same error as above, see here. When you defined the constructor outside the class, though, it was attempting to link it even without the instantiation, resulting in the error even without child a(5);.

Related

c++ statically assert that a function is never called

For some complicated reasons I want to create default constructor (alongside my normal constructors) that always throws. I want it to be there, but I also want it never to be called. It is pretty obvious that during runtime I can check for that thrown exception and for example terminate program when I catch it, but the ideal solution would be to have it checked during compilation.
So my question is: can I statically assert somehow that a function will never be called? I've looked at functions in <type_traits> but I don't see anything there that would help me. Is there some c++ dark magic that I could use to achieve my goal?
I don't have a code example, because what would even be in there?
PS. Yes. I am sure that I want to have a function and disallow everybody of calling it. As I stated previously reasons for that are complicated and irrelevant to my question.
EDIT. I can't delete this constructor or make it private. It has to be accessible for deriving classes, but they shouldn't call it. I have a case of virtual inheritance and want to "allow" calling this constructor by directly virtually derived classes (they won't call it, but c++ still requires it to be there), but no in any other classes deeper in inheritance chain.
EDIT 2. As requested I give a simplified example of my code.
#include <stdexcept>
class Base {
protected:
Base() { throw std::logic_error{"Can't be called"}; }
Base(int); // proper constructor
private:
// some members initialized by Base(int)
};
class Left: virtual public Base {
protected:
Left(int) {}
// ^ initialize members of Left, but does not call Base()!
// Though it seems that it implicitly does, Base() is never actually called.
};
class Right: virtual public Base {
protected:
Right(int) {} // The same as in Left
};
class Bottom: public Left, public Right {
public:
Bottom(int b, int l, int r): Base{b}, Left{l}, Right{r} {}
// ^ Explicitly calling constructors of Base, Left, Right.
// If I forget about calling Base(int) it silently passes
// and throws during runtime. Can I prevent this?
};
EDIT 3. Added body to Left's and Right's constructors, so that they implicitly "call" Base().
As you've stated in your comments that you never want to instatiate Base, Left or Right object, then you should make them abstract, even by some empty method:
class Base {
private:
// ...
virtual void DefineIfNonAbstract() = 0;
};
class Bottom: public Left, public Right {
void DefineIfNonAbstract() final {};
// ...
};
Trust your compiler. When it sees that DefineIfNonAbstract is private and none of its parents implemented it, it's not going to put it into a vtable.
You're Bottom class is already 16 bytes in your example for both gcc and clang (likely a pointer for each virtual inheritance). Adding the abstract method doesn't change that.
In the comments you expressed concern that this might not be safe, and sent me a link to CppCoreGuidelines:
I.25: Prefer empty abstract classes as interfaces to class hierarchies
Reason
Abstract classes that are empty (have no non-static member data) are
more likely to be stable than base classes with state.
They're referring to design choices here, not whether it causes undefined behaviour or something. In our case we're actually enforcing your design, not changing it.
The whole thing likely needs a serious rework in design. Inheritance in general is rarely a good choice - virtual inheritance even rarer.
If your link time optimization is up to the challenge, you might be able to have the problematic function call a never-defined function.
#include "Base.h"
// An anonymous namespace (or a static function) might be caught as missing
// while compiling this translation unit, so use a suggestive namespace name.
namespace DoNotDefine {
// Declare a function without a definition.
// The name is intended to make the error message easier to digest.
void DisallowedConstruction();
} // namespace DoNotDefine
Base::Base()
{
DisallowedConstruction();
}
In theory – I am not claiming that any particular linker is up to the task – the linker could eliminate unused function definitions before checking for missing definitions.
If nothing actually calls Base::Base() then such a linker would eliminate its definition before complaining that DisallowedConstruction() has no definition. After eliminating Base::Base(), there is no longer a call to DisallowedConstruction() so no problem.
If something did actually call Base::Base() then linking would fail because of there is no definition for DisallowedConstruction().
Again, I am not claiming that this will actually work with your compiler chain, only that it could work in theory.
For lesser compilers, I would suggest defining a pure virtual function in Base. Keep this pure virtual until you hit a class that uses non-default construction for Base. That ensures that no one instantiates a default Base. A bit awkward, but effective.
However, this has the drawback that the compiler cannot enforce this convention. This convention could be innocently broken. For example, someone might change a class from using non-default construction of Base to default construction and forget to remove the definition of the special function.

Overriding overloaded methods hides some of the overloads [duplicate]

This question already has answers here:
Why does an overridden function in the derived class hide other overloads of the base class?
(4 answers)
Closed 5 years ago.
Suppose I have the following classes:
class Base
{
public:
virtual void myMethod()
{
}
virtual void myMethod(int x)
{
}
};
class Derived : public Base
{
};
In this situation the following code compiles just fine.
int main(void)
{
Derived obj;
obj.myMethod();
return (0);
}
The problem arises when I try to override one of myMethods like below.
class Derived : public Base
{
public:
virtual void myMethod(int x)
{
}
};
Now the code won't compile and gives the error:
error C2660: 'Derived::myMethod' : function does not take 0 arguments
I have overridden one of the overloaded functions and apparently this has hidden the other one from Derived class. To get rid of the error I have to override all the overloads. This is against my expectation and doesn't seem rational to me. Why does this code behave this way?
The problem can be reproduced here.
Indeed, declaring a function in one scope hides anything with the same name in a wider scope, so your override in the derived class hides the overload in the base class.
This is usually not a problem, since you'd usually interact with polymorphic classes via the base class; and usually what you want, since it prevents changes to the base class from unexpectedly changing the behaviour of code that does interact with the derived class.
But you can easily bring it back into the derived class's scope if you want:
using Base::myMethod;
or refer to the function by qualified name:
obj.Base::myMethod();
your compiler is 100% right.
you overloaded your function to take an integer as argument, then this function hid all of the base class function - so obj calls myMethod(int) be default , yet you don't provide your function an integer.
if you fix your code to be
obj.myMethod(4);
the problem solved.
when overriding a function in the derived class - it hides all the other base class overloads. one can still call the base class with this syntax :
obj.Base::myMethod();
In more in depth answer , this is WHY it happens.
first of all, we need to understand HOW the compiler compiles Object oriented code. remember - the functions compiles into assembly commands and they sit in the code segment. the variables compiles into rows of memory that sit wither in the stack , heap or data segments. functions sits in on part of the application , the variables in a complete different areas. how does the compiler compile a class with variables AND functions? well, it doesn't. the idea goes like this:
let's say a have a class named X with some variables and some functions
1) take all the member functions and bring them out of the class
2) add another argument to each-now-globally-declared functions - const X* this
3) each time you see the syntax x.someFunc(args..) change it to be someFunc(args..,&x)
4) in the functions - if you don't recognize a symbol - try attaching it a this-> and see if you can compile this
5) compile X as C struct and the other as C functions
6)do the same for derived classes
(of course , there is the virtual table issue , but let's stop here)
IN YOUR EXAMPLE:
the psuedo code that might represent the compiler parsed-code is
struct Base{}
struct Derived{}
void myMethod(const Base* this);
void myMethod(int x,const Base* this);
void myMethod(int x, const Derived* this);
//what you tried to do is :
myMethod (&obj);
but the compiler can't find any function that matches these arguments!
this is not very intuitive for someone who don't initially knows how object oriented compiles, but it makes more sense after understanding this compiling procedure.
By overriding the function in Derived class you hide all overloaded implementations of that function name existing in Base class.
Therefore overriding void Base::myMethod(int) with void Derived::myMethod(int) generates code only for void Derived::myMethod(int) and doesn't for void Derived::myMethod().
As mentioned before you can call Base's function explicitly:
obj.Base::myMethod().

Call inherited method inside template function

I have a template method in a parent class, that should call another method from the base class. It works, if the method is explicitly defined in the base class, but it doesn't work if the method is inherited. I can't figure out what's exactly wrong with this code (although I know it's a little weird :)
class A
{
protected:
virtual void someMethod()
{
}
template <class TBaseClass>
void templateMethod()
{
TBaseClass::someMethod();
}
};
class B : public A
{
};
class C : public B
{
protected:
virtual void someMethod()
{
templateMethod<A>(); // this works
templateMethod<B>(); // this doesn't
}
};
This ends up with compiler error:
error C2352: 'A::someMethod' : illegal call of non-static member function
What exactly is wrong? I'm not looking for workarounds, that's easy. I'd like to know why is this incorrect.
In template <TBaseClass> void A::templateMethod() the invocant, this, is of type A *. So when you try to call B::someMethod on it, the compiler won't recognize it a object method call, because B is not a base class, but it can still be a static method call, so the compiler will try that, find B::someMethod inherited via A and complain it is not static. The fact that A is a base class of this is not relevant; only that B is not.
The issue is that class A is not automatically granted access to class B. The methods within the class don't know that the current instance of A is actually of type B.
To do what you're trying, you need to cast A to the target type:
template <class TBaseClass>
void templateMethod()
{
static_cast<TBaseClass*>(this)->someMethod();
}
This will work if the particular instance of A you're calling really is a B (as it is in the example you give). There is no type checking done here to be sure it is. If you pass a class that is not in the inheritance hierarchy you will be in the work of undefined behavior.
That said, your example has "someMethod()" as virtual. If you're doing what I just did here then making that method virtual may not make sense, as you are explicitly saying which instance you want. If you do leave it virtual, then just calling someMethod() directly in A will get you the most derived instance.
I think it's not working because you are trying to call a static method.
Static methods can be inherited but they can't be virtual.
Thats why A::someMethod will work and B::someMethod won"t work.

Delete virtual function from a derived class

I have a virtual base class function which should never be used in a particular derived class. Is there a way to 'delete' it? I can of course just give it an empty definition but I would rather make its attempted use throw a compile-time error. The C++11 delete specifier seems like what I would want, but
class B
{
virtual void f();
};
class D : public B
{
virtual void f() = delete; //Error
};
won't compile; gcc, at least, explicitly won't let me delete a function that has a non-deleted base version. Is there another way to get the same functionality?
It is not allowed by the standard, however you could use one of the following two workarounds to get a similar behaviour.
The first would be to use using to change the visibility of the method to private, thus preventing others from using it. The problem with that solution is, that calling the method on a pointer of the super-class does not result in a compilation error.
class B
{
public:
virtual void f();
};
class D : public B
{
private:
using B::f;
};
The best solution I have found so far to get a compile-time error when calling Ds method is by using a static_assert with a generic struct that inherits from false_type. As long as noone ever calls the method, the struct stays undefied and the static_assert won't fail.
If the method is called however, the struct is defined and its value is false, so the static_assert fails.
If the method is not called, but you try to call it on a pointer of the super class, then Ds method is not defined and you get an undefined reference compilation error.
template <typename T>
struct fail : std::false_type
{
};
class B
{
public:
virtual void f()
{
}
};
class D : public B
{
public:
template<typename T = bool>
void
f()
{
static_assert (fail<T>::value, "Do not use!");
}
};
Another workaround would be to throw an exception when the method is used, but that would only throw up on run-time.
The standard does not allow you to delete any member of a base-class in a derived class for good reason:
Doing so breaks inheritance, specifically the "is-a" relationship.
For related reasons, it does not allow a derived class to define a function deleted in the base-class:
The hook is not any longer part of the base-class contract, and thus it stops you from relying on previous guarantees which no longer hold.
If you want to get tricky, you can force an error, but it will have to be link-time instead of compile-time:
Declare the member function but don't ever define it (This is not 100% guaranteed to work for virtual functions though).
Better also take a look at the GCC deprecated attribute for earlier warnings __attribute__ ((deprecated)).
For details and similar MS magic: C++ mark as deprecated
"I have a virtual base class function which should never be used in a particular derived class."
In some respects that is a contradiction. The whole point of virtual functions is to provide different implementations of the contract provided by the base class. What you are trying to do is break the contract. The C++ language is designed to prevent you from doing that. This is why it forces you to implement pure virtual functions when you instantiate an object. And that is why it won't let you delete part of the contract.
What is happening is a good thing. It is probably preventing you from implementing an inappropriate design choice.
However:
Sometimes it can be appropriate to have a blank implementation that does nothing:
void MyClass::my_virtual_function()
{
// nothing here
}
Or a blank implementation that returns a "failed" status:
bool MyClass::my_virtual_function()
{
return false;
}
It all depends what you are trying to do. Perhaps if you could give more information as to what you are trying to achieve someone can point you in the right direction.
EDIT
If you think about it, to avoid calling the function for a specific derived type, the caller would need to know what type it is calling. The whole point of calling a base class reference/pointer is that you don't know which derived type will receive the call.
What you can do is simply throwing an exception in the derived implementation. For example, the Java Collections framework does this quite excessively: When an update operation is performed on a collection that is immutable, the corresponding method simply throws an UnsupportedOperationException. You can do the same in C++.
Of course, this will show a malicious use of the function only at runtime; not at compile time. However, with virtual methods, you are unable to catch such errors at compile time anyway because of polymorphism. E.g.:
B* b = new D();
b.f();
Here, you store a D in a B* variable. So, even if there was a way to tell the compiler that you are not allowed to call f on a D, the compiler would be unable to report this error here, because it only sees B.
I have a virtual base class function which should never be used in a particular derived class.
C++11 provides a keyword final which prevents a virtual function being overriden from.
Look: http://en.cppreference.com/w/cpp/language/final .
class B
{
virtual void f() final;
};
class D : public B
{
// virtual void f(); // a compile-time error
// void f() override; // a compile-time error
void f(); // non-virtual function, it's ok
};

Unexpected behaviour with a pure virtual function overridden in a derived type [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 8 years ago.
This is one of those cases where I thought I understood C++ virtual methods reasonably well, and then an example comes along where I realise that, sadly, I don't. Is there anyone reading this who can make sense of the following?
Here is some test code in which I define a very simple base class (actually just a two-element struct), an abstract template class containing a virtual void method, and then a derived class which inherits from both of them and explictly overrides the virtual void method with a concrete method.
#include <string.h> // For memcpy
#include <vector> // For std::vector
struct int_array_C
{
int n;
int* contents;
};
template <typename T> class array_template
{
public:
array_template<T>() {}
array_template<T>(const array_template<T> &source)
{
*p_n = *(source.p_n);
setPointers(&(source.local_contents[0]));
}
// ..and in reality, a bunch of other array manipulation functions
protected:
virtual void setPointers(const T* data) = 0;
int *p_n;
std::vector<T> local_contents;
};
class int_array : public int_array_C, public array_template<int>
{
public:
int_array() : array_template<int>()
{
n = 0; contents = NULL;
}
protected:
virtual void setPointers(const int* data)
{
p_n = &n;
local_contents.resize(n);
memcpy(static_cast<void *>(&local_contents[0]),
static_cast<const void *>(data), n*sizeof(int));
contents = &local_contents[0];
}
};
int main()
{
int_array myArray;
int_array yourArray(myArray);
return 1;
}
When the copy constructor is called in the second line of main(), the argument is an instance of the derived class which has a concrete setPointers() method. Therefore, when the template class's copy constructor is called and the call to setPointers() is encountered, I'd expect the rules of polymorphism to kick in and the derived class's setPointers() method to be called.
In fact, however, the compiler chokes on this; at compilation time I get a warning saying
"Warning: call of pure virtual function at line 18"
and at link time the linker fails with a message saying
error LNK2019: unresolved external symbol "protected: virtual void __cdecl array_template<int>::setPointers(int const *)" (?setPointers#?$array_template#H##MEAAXPEBH#Z) referenced in function "public: __cdecl array_template<int>::array_template<int>(class array_template<int> const &)" (??0?$array_template#H##QEAA#AEBV0##Z)
Exactly the same thing happens (with slight variation in the text of the error messages) using Visual C++ and Intel C++ on Windows and gcc on Linux, so it's obviously a genuine violation of language rules rather than just being a compiler quirk. Yet I can't see what the problem is.
So, what am I doing wrong and how might I make this work as intended?
In the execution of a constructor body for a class T the dynamic type is T. Any direct or indirect call of a pure virtual T member function here, is therefore invalid. It's some extra type checking security of C++, ensuring that you don't accidentally get into derived class code before the derived class sub-object has been properly initialized (or at least given the chance).
However, I don't understand why it ends up as a linking error.
Regarding solutions, this is a FAQ; essentially you have to somehow pass the derived class functionality or data up to the base class, and there are many ways to do that. As it happens I once convinced Marshall to include that FAQ item. So I can to some degree claim it as my answer to your problem. :-)
Update on the original code behavior.
Adding the following:
template< class T >
void array_template<T>::setPointers( const T* data )
{
using namespace std;
clog << "!pure virtual setPointers called!" << endl;
}
it turned out that with both Visual C++ 12.0 and g++ 4.8.2 it was called.
The call is Undefined Behavior so both compilers are in their right to produce such behavior, but still it surprised me. I'd think instead they would put a pointer to some error function in the vtable. Anyway, it explains the linking errors, with these two compilers.
Paul Griffiths nailed it with his comment under my original question:
"You can't call a derived class's virtual function from a base class constructor, because at the time it's called the derived class hasn't been constructed yet."
That's the critical thing: the call occurs in the constructor, and because the base class's constructor is called before the derived class exists, there is no concrete version of setPointers to call yet (at least, not in the new object that is in the process of being created; the fact that the old object being passed as an argument has one is irrelevant here).
The solution is pretty simple: move the copy constructor out of the template altogether and place it within the derived class instead. It's only a two-line function so it's not too painful to do this with each of my dozen or so derived classes, and it solves the problem.
[N.B. If anyone is wondering what all this is in aid of, this is part of a large mixed-language application. I want to have a set of container functions which have the functionality of a std::vector when used in C++, so that I can resize, reference, copy etc. at will, but then pass to a plain C subroutine expecting just the base struct. Everything except the template copy constructor has been working well for a long time now!]
You cannot call virtual methods from base class constructors and get derived class methods: those are set up after the base class is constructed.
Try changing the layout of your inheritsnce:
class int_array_impl:public int_array_C{...};
template<class T,class B>class array_template:public B{
//...
};
typedef array_template<int, int_array_impl> int_array;
make the method non-virtual, get rid of pure virtual stuff in array_template, and just blindlh invoke this->method. If B has it, it will be called.
Either forward constructors, or have a 4th class under array_template that provides custom ones.