Im currently learning OOP in C++.
class Base {
public:
Base() {}
protected:
SomeClass variable;
};
class Child : public Base {
public:
Child() {}
void method() {
// Access variable
}
};
When accessing a member variable in the base class from a derived class, what is the difference between these two notations?
this->variable
Base::variable
And what is preferred when?
The "full" expression naming that variable is:
this->Base::variable
It says:
The name is variable
It lives in the type Base
The object owning this instance is this
Since you're inside a scope where base members will be found automatically, you don't need Base::.
And, since you're inside a member function where all members will be found automatically, you don't need this->.
You might need Base:: to disambiguate from some other variable in scope, but the this-> part likely takes care of that for you already.
So, usually, you only need any of the following:
variable (normally)
this->variable (if something from another scope is hiding it)
Base::variable (if something in the current type is hiding it)
As for what's "preferred"… as long as you've satisfied your needs, you can do whatever you like. But simpler is usually deemed "better", and will invite fewer questions from others reading your code.
There is a third option missing: Just variable.
And what is preferred when?
The one that is most pleasing to your aesthetics.
There are some cases in which some of the options won't work. In such cases, it is preferable to use those that do work. Examples are: Plain variable name cannot be used if it has been shadowed by another variable. Qualified name cannot be used in some cases where the base depends on a template variable.
Related
I am a beginner in C++, I had a question regarding nested class in C++, how do you access the protected or private member of an enclosed class?
class A{
class B{
protected:
B(){};
};
B var; <=== error as the constructor B is protected
};
One solution is making constructor of B public, but this exposes it'a scope and other function can instantiate it, which I don't want. What's a way to do deal with this ?
You can use friend class:
class A
{
class B
{
friend class A; //<-- makes A a friend of B
protected:
B(){};
};
B var; //<-- OK
};
I believe the question that was asked does not get at the real issue. It is almost an XY problem, but fortunately it has sufficient hints for the real issue to be deduced. Still, in the interest of propriety, I will address the question that was asked before addressing what I believe is the real issue.
how do you access the protected or private member of an enclosed class?
The same way you grant such access when the classes are not nested: the class with the protected or private member declares the other class (or function) as a friend. Just be aware that this is a bit of a sledgehammer approach, so it is advisable to consider alternatives first.
One solution is making constructor of B public, but this exposes it's scope and other function can instantiate it, which I don't want.
No, it doesn't expose anything outside A. You have declared B as a private type within A, which means only A can reference B. With your current setup, there is no functional difference between making A a friend of B and making all members of B public. In either case, A has full access to B and nothing outside A knows that B exists.
While I suspect that B is supposed to be public, the OP has had days to correct this detail. In addition, the OP posted a new question after this possible oversight was pointed out, so I must conclude that the OP does not regard it as an oversight.
Now we get to what I believe is the real issue: how to construct a public nested class from the outer class without allowing public construction.
What's a way to do deal with this ?
If there is a possibility that B might become a public type at some point (a reasonable thing to guard against), you should consider alternatives to friendship. One alternative is to put the constructor of B under lock-and-key. This could be extended to other private members of B, but that is perhaps not necessary.
One advantage of this approach is that access is granted to only the constructor, not to all private members. This helps preserve encapsulation. Furthermore, this approach allows construction to be handed off to helper functions, such as those from the standard library. For example, an emplace_back method for a standard container could construct a B object as long as the method was given a key. This might be more convenient than relying on friendship, depending on how B objects are to be used.
The key
The "key" is a private class of A. It is likely going to be an empty class, as it does not need functionality. All the key needs to do is exist and be inaccessible outside A.
class A{
private:
class KeyForB {};
// Rest of the definition of A
};
The lock
The "lock" is a constructor that accepts the "key" as a parameter. This parameter will not be used by the constructor; all it does is signify that the caller is allowed to call the constructor.
class B{
public:
/* explicit */ B(KeyForB /* unnamed */) : B() {}
protected:
B() {}
};
There are a few details worth looking at. First, you might have noticed that B just used a private member of A! How? There is a special rule that says that nested classes are considered part of the outer class, and as such they can access the private (and protected) members of the outer class – no friend declaration necessary.
Second, the lock delegates to the protected constructor. This may seem odd, but it does serve a purpose. Not only does it keep the default constructor available to B, but also it allows the compiler to optimize away the lock and key. Consider what would happen if the constructor was so large that the compiler opted to not inline it. If a function is not inlined, then parameters cannot be optimized away. In this case, that would mean that a KeyForB would need to be constructed and placed on the call stack. In contrast, the lock is so simple that it should be inlined under any level of optimization. It gets inlined to a call to B() and the unused KeyForB is eliminated from the executable.
Third, there is a comment acknowledging that some coding guidelines recommend marking as explicit most constructors that take a single parameter. This is sound advice. However, in this case, the only reason to create a KeyForB object is to construct a B object. So in this case, it might be acceptable and convenient to leave this conversion implicit.
Putting it together
The only remaining piece is to write a constructor for A, as the compiler-provided default constructor is deleted because it would be ill-formed.
class A{
private:
class KeyForB {};
//public: // <-- possible future change
class B{
public:
B(KeyForB) : B() {}
protected:
B() {}
};
public:
// Default constructor
A() : var(KeyForB{}) {}
private:
B var;
};
It might be worth noting that if the type of var were to change from B to std::shared_ptr<B>, this approach would not run into "make_shared for friend class throwing error", as giving a key to make_shared would enable construction.
I've been trying to understand a piece of code that goes like this:
class A {
// some class definition
}
class B {
public:
virtual A *someMethod();
virtual class A *someOtherMethod();
}
I can't seem to understand the difference (or if any exists, for that matter) between someMethod and someOtherMethod - both appear to be virtual methods and both are overridden in classes that inherit from B.
Could someone shed some light on this virtual class syntax?
A is the class name, and class A is the elaborated type specifier.
If there's nothing else called A, then both refer to the class called A.
If there were something else (a function or variable, perhaps) called A, then an unqualified use of A would refer to that. You'd need the elaborated specifier class A to refer to the class. As mentioned in the comments, you can also use class A without a previous declaration of the class; the use of the elaborated specifier is enough to introduce the class name into the innermost namespace.
It has little to do with virtual function syntax; both forms can be used to specify the type, whether as the return type of a function or in any other context.
In C you used to have to write struct S to refer to a structure. In fact there was this pattern to deal with it: typedef S struct {}, which creates an unnamed structure, then gives it the name S through type aliasing.
C++ retained this ability, but aliases raw types automatically. In your case, A is a type alias to the formal name class A. Of course the automatic alias won't work if you have more than one A, but that's also a pretty big code smell.
TL;DR: both functions return the same thing. It's a remnant of C for backwards compatibility and extremely frowned upon when used.
I want to define the object of a class within a structure and access function members of the class. Is it possible to achieve this?
With the following code I am getting a segmentation fault at ps_test->AttachToInput(2145);. I can't figure out the reason, everything looks correct to me:
class test
{
public:
test();
virtual ~test();
int init_app(int argc, char* argv[]);
virtual void AttachToInput(int TypeNumber, int DeviceNo=0);
}
struct capture
{
test h_app;
gint port;
};
main()
{
struct capture h_cap;
test *ps_test = &h_cap.h_app;
ps_test->AttachToInput(2145);
}
First of all, the only difference between a class and a struct in C++ is that a class' members are private by default and a struct's members are public by default. Compiler-generated ctors and dtors are visible in both cases - unless otherwise stated by the programmer (e.g. they move the default ctor into a private section). Otherwise construction and destruction of instances of user-defined types marked class wouldn't be possible without explicit, public declaration - thus defying the very purpose of compiler-generated functions.
So basically, what you do in your example is merely composition of two user defined types which is perfectly legal. When you create an instance of capture, an instance of test is created as well.
What you can't do is publicly access AttachToInput() from outside of test and derived types of test. You need to declare the function public in order for this line to compile:
h_cap.h_app.AttachToInput(); // error: member function of `test` is protected
On another, unrelated note (but I came across it so I mention it), your class test holds a raw pointer to char. Holding raw pointers is ok, if the lifetime of the entity that's being pointed is guaranteed to exceed the lifetime of the object that holds the pointer. Otherwise, it's very likely the object itself is responsible for the destruction of said entity. You need to be sure about who owns what and who's responsible for allocation and deallocation of stuff.
EDIT: It should be noted, that Alan Stokes proposed the same in the comment section while I wrote this answer. :)
EDIT2: Slight oversight, implicit default access is also assumed for base classes depending on how the derived class is declared. See What are the differences between struct and class in C++?.
I know this question has a similar title to this: C++: calling member functions within constructor? but I am asking a more general question.
Is it good practice to call member functions from within a constructor? It makes reading the code easier and I prefer the encapsulation type way of doing it (ie. each block of code has a single objective).
An illustrative example, in python:
class TestClass:
def __init__(self):
self.validate()
def validate(self):
# this validates some data stored in the class
Is this a better way of doing it than writing the validate code inside the constructor? Are there drawbacks to this method? For example is it more costly with the function overhead?
I personally prefer it for readability but that's just my preference.
Cheers
I don't think there is anything inherently wrong in calling member functions from a constructor provided that they are not virtual functions.
The problem with calling virtual member functions from a constructor is that a subclass can override the function. This will cause the constructor to call the overridden implementation in the subclass, before the constructor for the subclass part of the object has been called.
In Java, any one of the private, static or final access modifiers will make the method safe to call from a constructor by preventing a virtual call to the superclass method. I don't think these techniques are available in Python.
There is at least one associated "gotcha" you should be aware of:
N3797 12.6.2/14
Member functions (including virtual member functions, 10.3) can be called for an object under construction. Similarly, an object under construction can be the operand of the typeid operator (5.2.8) or of a dynamic_cast (5.2.7). However, if these operations are performed in a ctor-initializer (or in a function called directly or indirectly from a ctor-initializer) before all the mem-initializers for base classes have completed, the result
of the operation is undefined. [Example:
class A {
public:
A(int);
};
class B : public A {
int j;
public:
int f();
B() : A(f()), // undefined: calls member function
// but base A not yet initialized
j(f()) { } // well-defined: bases are all initialized
};
class C {
public:
C(int);
};
class D : public B, C {
int i;
public:
D() : C(f()), // undefined: calls member function
// but base C not yet initialized
i(f()) { } // well-defined: bases are all initialized
};
— end example]
The main problem with this is that the member function has to work with an object that may be only partially initialized. And if it (even accidentally) passes a reference to the object somewhere else, other code has to od the same. This can get pretty confusing and error-prone, especially once you start overriding such a function in a subclass.
So in general, this practice should be avoided or at least confined to functions that can't be overriden, and they should never pass a reference to the object being constructed to any other code.
I'm more familiar with C++ than Python, but I see no problem with calling member functions from constructors, especially when this practice is able to factor out similar code from multiple constructors. Anything that reduces redundancy is good in my books.
From a readability point of view it is definitely better. One thing you might have to ask yourself here though is whether the validate method is allowed to run after the object is initialized. If that is not the case, you can a) use some kind of private initialized variable or b) use the Builder pattern to get your objects into a valid state before using them.
Make sure the function is private. You do not want to mess with subclasses overriding it (Unless this is desired by design, in which case make it abstract/virtual).
first, this member function cannnot be virtural function,
second, this member function must be implemented in the same file, if you declare it in *.h, then implement it in *.cpp, gcc/clang will report this error undefined reference to
Typically the 'using' declaration is used to bring into scope some member functions of base classes that would otherwise be hidden. From that point of view it is only a mechanism for making accessible information more convenient to use.
However: the 'using' declaration can also be used to change access constraints (not only for functions but also for attributes). For example:
class C{
public:
int a;
void g(){ cout << "C:g()\n"; }
C() : a(0){}
};
class D : public C{
private:
using C::a;
using C::g;
public:
D() { a = 1; }
};
int main(void){
D d;
cout << d.a << endl; //error: a is inaccessible
C *cp = &d;
cout << cp->a << endl; //works
d.g(); //error: g is inaccessible
cp->g(); //works
return 0;
}
I think this limitation of access in the derived class is actually of no use, because you can always access g() and a from a pointer to the base class. So should't there be at least some kind of compiler warning? Or wouldn't it been even better to forbid such limitation of access by a derived class? The using declaration is not the only possibility to add constraints to access. It could also be done via overriding a base class' function an placing it in a section with more access constraints.
Are there some reasonable examples where it is indeed nessecary to limit access in such a way? If not I don't see why it should be allowed.
And another thing: at least with g++ the same code compiles well without the word 'using'. That means for the example above: it's possible to write C::a; and C::g; instead of using C::a; using C::g; Is the first only a shortcut for the latter or are there some subtle differences?
//EDIT:
so from the discussion and answers below my conclusion would be:
- it's allowed to limit access constraints in derived classes with public inheritance
- there are useful examples where it could be used
- it's use might cause problem in combination with templates (e.g. a derived class could not be a valid parameter for some template class/function any more although it's base is)
- a cleaner language design should not allow such use
- compiler could at least issue some kind of warning
With regard to your declaration without using: These are called "access declarations", and are deprecated. Here is the text from the Standard, from 11.3/1:
The access of a member of a base class can be changed in the derived class by mentioning its qualified-id in
the derived class declaration. Such mention is called an access declaration. The effect of an access declaration qualified-id; is defined to be equivalent to the declaration usingqualified-id; [Footnote: Access declarations are deprecated; member using-declarations (7.3.3) provide a better means of doing the same things. In earlier versions of the C++ language, access declarations were more limited; they were generalized and made equivalent to using-declarations - end footnote]
I would say that most often it's not good to change public members to private or protected members in the derived class, because this will violate the substitution principle: You know a base class has some functions, and if you cast to a derived class then you expect those functions to be callable too, because the derived class is-a base. And like you already mentioned, this invariant is already enforced anyway by the language allowing to convert (which working implicitly!) to a base class reference, or qualifying the function name, and then calling the (then public) function.
If you want to forbid someone calling a set of functions of the base, then i think this hints that containment (or in rare cases, private inheritance) is a better idea.
While the using declaration you showed does provide a mechanism to change access level (but only down), that is not the primary use of it in such a context. A using context there is primarily intended to allow access to functions that would otherwise be shadowed from the base class due to the language mechanics. E.g.
class A {
public:
void A();
void B();
};
class B {
public:
using A::B;
void B(int); //This would shadow A::B if not for a using declaration
};
The declaration
using C::a
brings "a" to the local naming scope so that you can later use "a" to refere to "C::a"; since that, "C::a" and "a" are interchangeable as long as you don't declare a local variable with name "a".
The declaration does not change access rights; you can access "a" in the subclass only because "a" is not private.