This question already has answers here:
Access to protected member through member-pointer: is it a hack?
(4 answers)
Closed 4 years ago.
Consider
class A {
protected:
int m;
};
class B : public A {
void foo(A& a) {
a.m = 42; // ill-formed
}
void bar(A& a) {
auto pm = &B::m;
auto pm2 = static_cast<int A::*>(pm);
a.*pm2 = 42; // is this ok?
}
};
Trying to access A::m directly is ill-formed according to [class.protected]. However, it appears that we can always (?) circumvent this using static_cast, which allows a derived-to-base cast with pointers to members. Or is this somehow UB?
[Coliru link showing that bar compiles]
Yes, you can circumvent the protected mechanism in this way by using static_cast.
I think this is not undefined behavior in this particular case.
By using the static_cast you tell the compiler two things:
You ask the compiler to convert the B pointer into an A pointer.
You tell the compiler that this is ok to do so.
For 1. the compiler applies very limited checks of whether this is okay or not, and for static_cast it allows to cast from derived to base and the other way round, and that is it. So the compiler is happy. Whether a variable or pointer is protected or public is not part of the variable or pointer type. Neither pm nor pm2 carry the protected information.
For 2. the compiler completely leaves it up to you to make the decision whether this is okay or not in your design. It is not undefined behavior. It may still not be a good idea. pm2 is just a pointer to an int in A. You can reset it to a pointer to a different int in A which is public.
The background is that access control in C++ is generally per-class, plus there are some extra rules around protected which try to provide some level of access control on a per instance basis, but this protection is not perfect as you have demonstrated in your interesting question.
Related
This question already has answers here:
C/C++ Struct vs Class
(7 answers)
Closed last year.
Is memory allocation for class (when initializing an object) is the same as struct? I know that when we initialize struct,
struct example {
int a;
double b;
int c;
}
the memory allocated will be = (0-4) int, (8-16) double, (16-20) int. (If I am not mistaken)
What if we want to initialize
class Example {
private:
int a;
double b;
int c;
public:
Example();
}
Example object();
?
What's the memory allocation behavior when the object is initialized? Is it the same as struct?
Yes. Literally the only difference between a class and a struct is that in a struct, member-variables/methods listed in the first section of the declaration (above any public:/protected:/private: lines) are treated as public, whereas in a class they are treated as private.
Ask sizeof. It is always correct. In this simple case, the class is guaranteed to have no hidden members; in general that isn't true.
The rule isn't about class vs struct; the only difference is the default in struct is public members but class is private members. The rule is about when you use expensive things. When you add virtual in, the sizes of things start to change. When you add virtual inheritance, things get a lot bigger.
You can only use RTTI on a class that has a virtual member. See How to get the typeid of a void* pointer? for details.
You have asked a further question; whether you can just add up the sizes of the members. The answer is a definite "No". You can't do that. On my platform, that struct may well take up, 24 bytes due to alignment (the double wants to be 8 byte aligned).
This question already has answers here:
Can virtual functions be constexpr?
(3 answers)
Closed 1 year ago.
I'm implementing a pure virtual function in a C++ derived class, and mark the method final. I would also like to mark the function constexpr, but it appears the standard doesn't allow this.
Is there any practical reason why it would be difficult for compilers to implement this? Or is such a feature omitted due to the usual "this feature wasn't deemed to be important enough to add to the standard" thinking?
Based on the comments, it seems my original question didn't make it clear I am asking about constexpr final functions. The following code illustrates what I am trying to compile:
struct A {
virtual int foo() const;
};
struct B : public A {
// Note that this function is final, and is therefore no longer
// polymorphic in types derived from B (e.g., the function call
// no longer requires a lookup in the virtual method table
// when the compile-time type is known to be derived from B)
constexpr int foo() const final {
return 0;
}
};
Note that this was flagged as a duplicate of Can virtual functions be constexpr?, since in C++20, the above code would compile with or without the final keyword.
C++20 adds support for this code.
On godbolt, we can try it out: https://godbolt.org/z/f64e93dzY
It looks like this is Defect Report 647
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I know how useful it is to declare variable as a reference or pointer in a function, but I just wonder why we declare it as a reference in the private section of a class.
example
class DoSomething
{
private : int& t_; // why not just 'int t;'
};
How about if we declare the variable without reference, and define the object of a class as a pointer or reference? Is this not good practice?
If you declare the variable as int, its value would be "divorced" from the variable from which it has been initialized. If you keep it a reference, the variable would be "tracking" the variable with which it has been initialized:
class demoRef {
int &r;
public:
demoRef(int& x) : r(x) {}
void show() {cout << r << endl;}
};
class demoCopy {
int r;
public:
demoCopy(int& x) : r(x) {}
void show() {cout << r << endl;}
};
int main() {
int x = 123;
demoRef dRef(x);
demoCopy dCopy(x);
dRef.show();
dCopy.show();
x = 456;
dRef.show();
dCopy.show();
return 0;
}
This code produces the output below:
123
123
456
123
Demo on ideone.
Note: this is only an illustration of what you can do with a reference to an int. It is not meant to imply that you should do something like this without being extra careful, because a hidden reference like this makes your code harder to read.
There are many reasons you might have a reference member. An example from the standard library is the back_insert_iterator, which keeps a reference (or a pointer) to a container in order to call that container's push_back function.
Note that with any class like this, which stores a reference or pointer to another object, you need to take the same care as you would with a raw reference or pointer. That is, you need to be wary of dangling references, and ensure that you don't use the reference past the lifetime of the referent.
When you store a reference to a variable in a class, the outcome of changing the variable is:
You can change the variable in a member function of DoSomething and have that change be visible outside the class.
You can change the variable outside DoSomething and have that change be visible inside DoSomething.
The key question is: Where is it useful?
I have often found it useful in a functor that is passed to some of the functions in the standard library.
#BenjaminLindley already gave you a very good example of that.
I have often found it useful in Factory Patterns when a concrete Product is created using the data stored in a concrete Factory but the data is too expensive to copy.
I have used it in classes that implement a functional interface. These classes hold references to other data when:
3.1. The class needs to access to the data but it is too expensive to copy the data.
3.2. It makes no sense to copy the data or copying is prohibited by design (such as std::ofstream).
3.3. The class needs to update the data and make it visible to the calling code.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
class test {
public:
test(int value = 0): x(value) {}
int& get(){
return x;
}
private:
int x;
};
this will allow client code to mutate the private members
this is legal in C++, but why ?
Is there any situation where you would actually need to break the class encapsulation ?
Make a member as private, means you can not access it directly. But nothing restricts you to access it indirectly via a public member. It depends on you design. You can even do this:
class test {
public:
test() : x(y) {}
int &x;
private:
int y;
};
In your class, assume you want count how many times a member is read/write. So, you can make it private then put a member function which returns a refernce to the variable:
class test {
public:
test(int value = 0): x(value), count(0) {}
int& get(){
count++;
return x;
}
private:
int x;
int count;
};
I hope this example shows how making a member as private and then putting an indirect access to it can be useful.
Ffirst of all let's consider implementing what you describe. It would be very onerous to properly do so. Your example is easy enough. But what if the reference flowed through a number of functions before it reached the function that exposed it? The compiler would have to do exceptionally complex static analysis, beyond the levels of static analysis that are reasonable to expect from compiler writers.
So even if the designers wanted to ban this, it would not have been tractable to do so. Would the designers have wanted to stop this? Very doubtful. Had they done so, how would the [] operator be implemented on a container or a string?
Is there any situation where you would actually need to
break the class encapsulation
As example of the [] operator on containers and strings shows, this feature is in fact used to support encapsulation.
Why? Because C++ mainly tries to let you do whatever you want and not get in your way; it doesn't try very hard to keep you safe. If you want a safe language, use something else. You have something like object-orientation if you want to, but if you want to break out of that, more power to you. With great power comes great responsibility.
It's worth nothing that you don't even need this to break encapsulation; you could simply reinterpret a pointer to "test" as an integer and access the private field this way.
This question already has answers here:
When should I make explicit use of the `this` pointer?
(12 answers)
Closed 9 years ago.
I wonder if there is some reason or not to use this in a attribute class?
class Foo
{
private:
int m_foo;
public:
int getIntance() { return this->m_foo; }
}
Other than the fact its say that this is the current class, are there others reasons?
No, do not use it. In that particular case, it is not needed, and this is less typing :
int getIntance() { return m_foo; }
Less you write is better. Even for people reading you code (they'll have less to read)
this is less typing. It is not mandatory in this particular case. There is no reason to use this keyword unless if you want to pass the current instance of your object to a function for example.
You can simply write :
int getIntance() { return m_foo; }
It is weird to call a method getInstance to return an int. It is quite uncommon...
There's no reason to use this, except when, for example, you want something outside the class to point to your instance (let's say, you add your instance - this - to a list of pointers).
In your example, this is redundant, since m_foo could easily have been returned by return m_foo; without any problem.
However, this can only be used in non-static member functions, or else it won't compile.