I am having some issues with const/mutable and protected. Maybe these are confusing me a little bit so I will give an example.
class Base
{
virtual void foo() const ;
protected :
void bar( int y ){ d_x = y } ;
private :
mutable int d_x ;
}
So base class has as a virtual foo.
class Derived : public Base
{
void foo() const { bar(5); }
private :
mutable int d_x ;
}
so in my derived class I have implemented foo, which class bar which then writes to the private d_x.
I would assume is fine - but compiler says :
passing 'Derived' as 'this' argument of bar discards qualifier.
Why is that? I thought by using mutable I could make my member function to be const.
From inside a const qualified function (such as foo), you may only call other const qualified functions. And bar is a not a const qualified function.
The fact bar only touches d_x is immaterial. The mutability of d_x only means that a const qualified member function can modify it directly. And formally, bar is allowed to modify any member (if they were to exist).
Const member function foo calls non-const member function bar. Calling bar requires a non-const this, whereas this is a pointer to const inside foo.
Either bar must be const or foo must be non-const.
Related
I understand that specifying a member function "const" allows us to call it from a const object, but why do we have to explicitly write "const" next to the member function? Why can't the compiler figure out that
int getFoo() {
return m_foo;
}
is indeed "const" for all intents and purposes?
Because C++ allows declarations to be in different places to definitions.
If all you have is
class Bar {
int m_foo;
public:
int getFoo();
};
can you safely call getFoo on a const Bar?
Say I have two functions, and one calls the other to work.
void friendList::addFriend(string userNameIn)
{
if(friendList::isFriend(userNameIn))
//add friend
}
bool friendList::isFriend(string name)
{
//check if user name exists
}
Is this allowed? I am getting errors for:
In member function 'void User::addFriend(std::string)':
and error: cannot call member function 'bool friendList::isFriend(std::string)' without object
Is it because the functions aren't completely filled out yet?
Yes, functions can of course call other functions in C++.
Doing so is not a case of functions being put inside other functions: your question title is misleading.
It looks as if addFriend might be a static member function, and as such it has no object, whereas isFriend is a non-static member function. When a static member function of a class calls a non-static member function, it must supply an object:
class someclass {
// ...
static void static_member();
void nonstatic_member();
};
void some_class::static_member()
{
nonstatic_member(); // error
some_instance.nonstatic_member(); // okay
}
void some_class::nonstatic_member()
{
}
static_member cannot call nonstatic_member, but it can invoke nonstatic_member on an object. It will work provided that some_instance is suitably defined somewhere as an instance of some_class.
The compiler error:
cannot call member function [...] without object
Suggests to me that you are trying to call a non-static member function directly, rather than through an object. For example:
class Foo
{
public:
int DoIt() {}
};
int main()
{
Foo::DoIt();
}
If that's what you're trying to do, you can't. Non-static member functions need to be called through an object:
int main()
{
Foo foo;
foo.DoIt();
}
If you must refrain from calling through an object, then you need to make the member function static:
class Foo
{
public:
static int DoIt() {}
};
int main()
{
Foo::DoIt(); // OK
}
But then, DoIt won't be able to call other non-static member functions.
You want to use the 'this' pointer. this->isFriend(userNameIn)
Let's say I have this example template:
template<class T>
class Wrapper
{
virtual T* ReturnPtr() = 0;
};
And then I inherit from it:
class Buffer; //some class
class BufferWrapper : public Wrapper<Buffer>
{
virtual Buffer* ReturnPtr(); //<< (1.)
}
Is this the way to do it properly? When I write it like this it
gives me no intellisense errors, but once I write ReturnPtr()
somewhere,it tells me "the object has type qualifiers that are not
compatible with the member function".
Does this mean it's impossible to use virtual methods like that?
Intellisense shows that message when you are calling a non-const function on an object that is const. As we can see, ReturnPtr is non-const. There are generally two reasons you might see this message. The first is when you are trying to call ReturnPtr on a const object of type BufferWrapper:
const BufferWrapper bw;
bw.ReturnPtr(); // Can't call non-const member function on const object
The second is when your BufferWrapper object is a data member of a class and you are calling ReturnPtr on it from within a const member function of that class:
struct SomeClass
{
BufferWrapper bw;
void SomeClass::SomeFunc() const
{
bw.ReturnPtr(); // Cannot call non-const member function here
}
}
Suppose I have a class Baz that inherits from classes Foo and Bar, in that order. The constructor for class Bar takes a pointer to a Foo object. What I would like to do is to pass this as the Foo object to the Bar constructor:
Baz () : Foo(), Bar(this) {}
A working example:
#include <iostream>
class Bar;
class Foo {
public:
virtual ~Foo() {}
virtual void parse_bar (Bar&) const = 0;
};
class Bar {
private:
const Foo * parser;
public:
Bar (const Foo * parser_in) : parser(parser_in) {}
virtual ~Bar() {}
void parse_self () { parser->parse_bar (*this); }
};
class Baz : public Foo, public Bar {
public:
Baz () : Foo(), Bar(this) {}
virtual void parse_bar (Bar &) const { std::cout << "Hello World\n"; }
};
int main () {
Baz baz;
baz.parse_self();
}
This happens to work on my computer, with my compilers (tested with a couple of them). However section 9.3.2 of the 2003 standard makes me a bit uneasy that I might just be getting lucky, that using this this way is undefined behavior. Strictly speaking, the initializer list is outside the body of the constructor. Here's the relevant text, emphasis mine:
9.3.2 The this pointer
In the body of a nonstatic member function, the keyword this is a non-lvalue expression whose value is the address of the object for which the function is called.
So is my usage legal and well-defined, or is it undefined behavior?
There are two points that have to be noted in this case.
Firstly, in the constructor initializer list this pointer refers to a non-constructed (or not-fully-constructed) object. It is OK to access such pointer, but the object it refers to can only be used in limited ways. See 12.7 in the language specification.
Secondly, in your specific example what you are actually doing is converting this pointer to Foo * type before attempting any access. This is completely safe since by that moment the Foo subobject is fully constructed. (I assume that, whatever access will follow, if any, will be restricted only to the fully constructed Foo subobject).
The only concern is this case is whether it is legal to convert this to Foo * type, i.e. whether the conversion process itself should succeed. The answer is: yes, in case of ordinary (non-virtual) inheritance such conversion is perfectly legal and safe (again, explicitly allowed in 12.7)
It is fine. The C++ standard actually clarifies the use of this pointers in initializer lists:
12.6.2 Initializing bases and members [class.base.init]
Paragraph 7: Names in the expression-list of a mem-initializer are evaluated in the scope of the constructor for which the mem-initializer is specified. [Example:
class X {
int a;
int b;
int i;
int j;
public:
const int& r;
X(int i): r(a), b(i), i(i), j(this->i) {}
};
initializes X::r to refer to X::a, initializes X::b with the
value of the constructor parameter i, initializes X::i with the
value of the constructor parameter i, and initializes X::j with
the value of X::i; this takes place each time an object of class X
is created. ] [Note: because the mem-initializer are evaluated in
the scope of the constructor, the this pointer can be used in the
expression-list of a mem-initializer to refer to the object being
initialized. ]
The type of the this pointer in the initializer of Baz is in fact of type Baz. Of course, you have to be mindful of the fact that not all of the members may have been initialized. Many, if not all, compilers set at their highest warning levels (which you really should be doing anyway) will warn about you passing a this pointer to the base class.
However, it looks like you're making it more complicated that it needs to be. Why not just put the virtual function parse_bar() in the Bar class, and forget about the Foo class?
#include <iostream>
class Bar
{
public:
Bar() {}
virtual ~Bar() {}
void parse_self () { parse_bar(); }
private: // Template method pattern
virtual void parse_bar() const = 0;
};
class Baz : public Bar
{
public:
Baz () {}
private: // Yes, this does override the private `parse_bar()` member!
virtual void parse_bar() const { std::cout << "Hello World\n"; }
};
int main ()
{
Baz baz;
baz.parse_self();
}
This does essentially the same function but with less code.
For a code like this:
class foo {
protected:
int a;
public:
class bar {
public:
int getA() {return a;} // ERROR
};
foo()
: a (p->param)
};
I get this error:
invalid use of non-static data member 'foo::a'
currently the variable a is initialized in the constructor of foo.
if I make it static, then it says:
error: 'int foo::a' is a static data member; it can only be initialized at its definition
However I want to pass a value to a in the constructor.
What is the solution then?
In C++, unlike (say) Java, an instance of a nested class doesn't intrinsically belong to any instance of the enclosing class. So bar::getA doesn't have any specific instance of foo whose a it can be returning. I'm guessing that what you want is something like:
class bar {
private:
foo * const owner;
public:
bar(foo & owner) : owner(&owner) { }
int getA() {return owner->a;}
};
But even for this you may have to make some changes, because in versions of C++ before C++11, unlike (again, say) Java, a nested class has no special access to its enclosing class, so it can't see the protected member a. This will depend on your compiler version. (Hat-tip to Ken Wayne VanderLinde for pointing out that C++11 has changed this.)
In C++, nested classes are not connected to any instance of the outer class. If you want bar to access non-static members of foo, then bar needs to have access to an instance of foo. Maybe something like:
class bar {
public:
int getA(foo & f ) {return foo.a;}
};
Or maybe
class bar {
private:
foo & f;
public:
bar(foo & g)
: f(g)
{
}
int getA() { return f.a; }
};
In any case, you need to explicitly make sure you have access to an instance of foo.
The nested class doesn't know about the outer class, and protected doesn't help. You'll have to pass some actual reference to objects of the nested class type. You could store a foo*, but perhaps a reference to the integer is enough:
class Outer
{
int n;
public:
class Inner
{
int & a;
public:
Inner(int & b) : a(b) { }
int & get() { return a; }
};
// ... for example:
Inner inn;
Outer() : inn(n) { }
};
Now you can instantiate inner classes like Inner i(n); and call i.get().
You try to access private member of one class from another. The fact that bar-class is declared within foo-class means that bar in visible only inside foo class, but that is still other class.
And what is p->param?
Actually, it isn't clear what do you want to do
Your Question is not clear but there is use case when you will get this issue .
Invalid use of non-static data member.
When you are using "non-static data member in another class try to not use with scope resolution operator
Example::className::memberData = assignivalue ;
instead of above try to use object of className class;
Example:: m_pClassName->memberData=assignValue;*