I have a simple object, of type "ObjectX", with a simple method called "doSomething()". I'd like to make doSomething ONLY accessable by other ObjectX's. In other words, if something that is either static, or not an object of type "ObjectX" tries to call doSomething, it will be unable to. However, if an object of type ObjectX tries to call the method, it WILL be able to.
This differs from a private method, in that, a private method can only be called from the same object it is in. If there were another object of the same type calling that method on a different object, it would be locked out.
private does almost exactly what you want. Only objects of the same type can use private methods, and other objects can call those functions on other objects (that is, private functions are not restricted to the invoking object).
The only thing that is not as you described is that that static functions in the same class can also use private functions. There is no language feature that lets you restrict a function to the object only (excluding static functions).
I don't know where you get your facts. A private function A::foo can be called by any object of type A. Be it on itself or on another instance.
class A
{
public:
void foo(const A& other) { other.priv(); }
private:
void priv() const {}
};
int main()
{
A a1, a2;
a1.foo(a2);
return 0;
}
In C++
Class A{
A a;
doSomething(){
a.doSomething();
}
}
The above code would work.And this is the reason copy constructor work.
Class B{
A a;
doSomethingElse(){
a.doSomething();
}
}
Above would not anyways work.
If you want to provide access to B as well make A a friend of B by specifying friend B; in class A.
Related
Assume the following:
class A {
public:
A();
protected:
int a;
};
class B : public A {
public:
B();
};
My questions:
Can I access (directly) the protected data members of A and maybe modify them without having to use public member functions?
Can I treat A inside B as an "existing" object so that I can return A by reference and be able to modify its data member?
I am new to C++. I tried couple things to treat "A" as an object but I keep getting error messages. Here is one thing I have tried:
A & B::getA() {
return A; //error: "A does not refer to a value"
}
Can I access (directly) the protected data members of A and maybe
modify them without having to use public member functions?
A protected member variable or function is very similar to a private member but it provided one additional benefit that they can be accessed in child classes which are called derived classes.
Can I treat A inside B as an "existing" object so that I can return A
by reference and be able to modify its data member?
In B you can directly access to A (public and protected) method and attributes.
Read here for more.
To return a reference to your base class you can write
A & B::getA() {
return *this;
}
to access A's protected data member you can simply write
a = 5;
Why does this compile:
class FooBase
{
protected:
void fooBase(void);
};
class Foo : public FooBase
{
public:
void foo(Foo& fooBar)
{
fooBar.fooBase();
}
};
but this does not?
class FooBase
{
protected:
void fooBase(void);
};
class Foo : public FooBase
{
public:
void foo(FooBase& fooBar)
{
fooBar.fooBase();
}
};
On the one hand C++ grants access to private/protected members for all instances of that class, but on the other hand it does not grant access to protected members of a base class for all instances of a subclass.
This looks rather inconsistent to me.
I have tested compiling with VC++ and with ideone.com and both compile the first but not the second code snippet.
When foo receives a FooBase reference, the compiler doesn't know whether the argument is a descendant of Foo, so it has to assume it's not. Foo has access to inherited protected members of other Foo objects, not all other sibling classes.
Consider this code:
class FooSibling: public FooBase { };
FooSibling sib;
Foo f;
f.foo(sib); // calls sib.fooBase()!?
If Foo::foo can call protected members of arbitrary FooBase descendants, then it can call the protected method of FooSibling, which has no direct relationship to Foo. That's not how protected access is supposed to work.
If Foo needs access to protected members of all FooBase objects, not just those that are also known to be Foo descendants, then Foo needs to be a friend of FooBase:
class FooBase
{
protected:
void fooBase(void);
friend class Foo;
};
The C++ FAQ summarizes this issue nicely:
[You] are allowed to pick your own pockets, but you are not allowed to pick your father's pockets nor your brother's pockets.
The key point is that protected grants you access to your own copy of the member, not to those members in any other object. This is a common misconception, as more often than not we generalize and state protected grants access to the member to the derived type (without explicitly stating that only to their own bases...)
Now, that is for a reason, and in general you should not access the member in a different branch of the hierarchy, as you might break the invariants on which other objects depend. Consider a type that performs an expensive calculation on some large data member (protected) and two derived types that caches the result following different strategies:
class base {
protected:
LargeData data;
// ...
public:
virtual int result() const; // expensive calculation
virtual void modify(); // modifies data
};
class cache_on_read : base {
private:
mutable bool cached;
mutable int cache_value;
// ...
virtual int result() const {
if (cached) return cache_value;
cache_value = base::result();
cached = true;
}
virtual void modify() {
cached = false;
base::modify();
}
};
class cache_on_write : base {
int result_value;
virtual int result() const {
return result_value;
}
virtual void modify() {
base::modify();
result_value = base::result();
}
};
The cache_on_read type captures modifications to the data and marks the result as invalid, so that the next read of the value recalculates. This is a good approach if the number of writes is relatively high, as we only perform the calculation on demand (i.e. multiple modifies will not trigger recalculations). The cache_on_write precalculates the result upfront, which might be a good strategy if the number of writes is small, and you want deterministic costs for the read (think low latency on reads).
Now, back to the original problem. Both cache strategies maintain a stricter set of invariants than the base. In the first case, the extra invariant is that cached is true only if data has not been modified after the last read. In the second case, the extra invariant is that result_value is the value of the operation at all times.
If a third derived type took a reference to a base and accessed data to write (if protected allowed it to), then it would break with the invariants of the derived types.
That being said, the specification of the language is broken (personal opinion) as it leaves a backdoor to achieve that particular result. In particular, if you create a pointer to member of a member from a base in a derived type, access is checked in derived, but the returned pointer is a pointer to member of base, which can be applied to any base object:
class base {
protected:
int x;
};
struct derived : base {
static void modify( base& b ) {
// b.x = 5; // error!
b.*(&derived::x) = 5; // allowed ?!?!?!
}
}
In both examples Foo inherits a protected method fooBase. However, in your first example you try to access the given protected method from the same class (Foo::foo calls Foo::fooBase), while in the second example you try to access a protected method from another class which isn't declared as friend class (Foo::foo tries to call FooBase::fooBase, which fails, the later is protected).
In the first example you pass an object of type Foo, which obviously inherits the method fooBase() and so is able to call it. In the second example you are trying to call a protected function, simply so, regardless in which context you can't call a protected function from a class instance where its declared so.
In the first example you inherit the protected method fooBase, and so you have the right to call it WITHIN Foo context
I tend to see things in terms of concepts and messages. If your FooBase method was actually called "SendMessage" and Foo was "EnglishSpeakingPerson" and FooBase was SpeakingPerson, your protected declaration is intended to restrict SendMessage to between EnglishSpeakingPersons (and subclasses eg: AmericanEnglishSpeakingPerson, AustralianEnglishSpeakingPerson) . Another type FrenchSpeakingPerson derived from SpeakingPerson would not be able to receive a SendMessage, unless you declared the FrenchSpeakingPerson as a friend, where 'friend' meant that the FrenchSpeakingPerson has a special ability to receive SendMessage from EnglishSpeakingPerson (ie can understand English).
In addition to hobo's answer you may seek a workaround.
If you want the subclasses to want to call the fooBase method you can make it static. static protected methods are accessible by subclasses with all arguments.
You can work around without a friend like so...
class FooBase
{
protected:
void fooBase(void);
static void fooBase(FooBase *pFooBase) { pFooBase->fooBase(); }
};
This avoids having to add derived types to the base class. Which seems a bit circular.
Simplification of the code to express the concept:
class classA
{
public:
private:
int a;
seta(int x);
};
//local prototype
void somefunction();
int main()
{
classA object; //create an object of the class
somefunction(object);
return 0;
}
void somefunction(classA &object)
{
object.seta(5);
}
}
If I move seta() to the public section of the class there is no error and it executes.
However, if I move seta() to the private section, I get the following error:
error C2248:
'anonymous-namespace'::classA::seta' : cannot access
private member declared in class 'anonymous-namespace'::classA'
If the function is private and only this class is calling it, why is there an issue?
EDIT I am passing the object from main to the local function
The function that is calling seta() is not part of classA, so this is an error; that's the very definition of private. If you were to make somefunction() a member of classA, or declare it to be a friend of classA, then this would work.
The function somefunction() is not a member function of classA. It's a function with global scope and cannot access the private function seta(), just as main() cannot access the private function seta().
This has nothing to do with "local functions" (functions defined inside other functions). This is simply about public and private members.
If a member is private, then it can only be accessed by other members of that class, or by explicit friends of the class.
private means that only member functions and friends can access it. Both must be listed in the class declaration, but are not:
class classA
{
public:
private:
int a;
seta(int x);
};
Being in the same file doesn't make the function a part of the class -- only the class declaration is used to determine what has access.
Private members can only be accessed by it's members and it's friends. Also every member function in C++, should have a return type. With that said -
void main() // 1
{
classA object; //2
somefunction();
}
Return type of main should be int.
Scope of object is only in main and cannot be accessed in somefunction with out explicitly passing it to the function.
On your Edit:
You are passing object to somefunction(classA) by value. So, a copy of the object ( main scoped) is made to somefunction scoped object. Though they bear the same name, both are different.
void somefunction(classA object)
{ // ^^^^^^ Is a copy of the parameter passed.
object.seta(5); // This call isn't actually modifying the original parameter passed.
}// life time of argument,object, ends here.
You should pass it by reference instead if you wish to modify parameter passed itself.
Firstly, to answer your primary question:
If the function is private and only this class is calling it, why is
there an issue?
The issue is that private class members can only be invoked by other members of that class. The function somefunction() is not a member of classA and therefore does not have access to private member seta().
As an aside, you should also think carefully about what you're doing when passing object to somefunction() from main. You're passing object by value, so you're creating a copy of object scoped to somefunction() which will be destroyed as soon as somefunction() terminates. IS that what you want?
I suspect that you're intending to pass object to somefunction() from main by reference, in which case you need to declare somefunction() as
void somefunction(classA &object)
seta(int x) is a private member of ClassA, so only ClassA or a friend class of ClassA can access to this member. somefunction() is none of them.
I am wondering if it is possible to call a derived class´ function from within a function called by the base constructor (shouldn´t it already be created when the code in the brackets are executed?)
#pragma once
class ClassA
{
public:
ClassA(void);
virtual ~ClassA(void);
void Init();
protected:
short m_a;
short m_b;
virtual void SetNumbers(short s);
};
include "ClassA.h"
#include <iostream>
ClassA::ClassA(void) : m_a(0), m_b(0)
{
Init();
}
ClassA::~ClassA(void)
{
}
void ClassA::SetNumbers(short s)
{
std::cout << "In ClassA::SetNumbers()\n";
m_a = s;
m_b = s;
}
void ClassA::Init()
{
this->SetNumbers(2);
}
#pragma once
#include "ClassA.h"
class ClassB : public ClassA
{
public:
ClassB(void);
virtual ~ClassB(void);
virtual void SetNumbers(short);
int x;
};
#include "ClassB.h"
#include <iostream>
ClassB::ClassB(void)
{
}
ClassB::~ClassB(void)
{
}
void ClassB::SetNumbers(short s)
{
std::cout << "In ClassB::SetNumbers()\n";
m_a = ++s;
m_b = s;
ClassA::SetNumbers(s);
}
Any suggestions how to do it?...
Thank You in advance :)...
No. All parts of B (starting with A, as it's base) are constructed before B's constructor is called. So, by the time SetNumbers is called, no part of B (except for the A part) has been constructed --- and that may include the v-table, so there's no way to know where that call is going to go.
Of course, there is a simple solution to this: Call B::SetNumber() from within B's constructor (That is, after all, the purpose of B's constructor)
You can't do this for the simple logical reason that while the base class is being constructed, the derived class hasn't even begun to be constructed. You can't call a member function on an object that doesn't exist (yet).
In practice, even if you managed to call SetNumbers and assign to the member variables of the derived class before they were initialized they would surely be overwritten when they finally get initialized. I admit it's a bit pointless to reason about this as we would be well outside defined behaivour.
No, sorry. :( It might compile in one or two C++ compilers, but it's not recommended. From the C++ FAQ Lite section 10.7:
[10.7] Should you use the this pointer
in the constructor?
[...snip...]
Here is something that never works:
the {body} of a constructor (or a
function called from the constructor)
cannot get down to a derived class by
calling a virtual member function that
is overridden in the derived class. If
your goal was to get to the overridden
function in the derived class, you
won't get what you want. Note that you
won't get to the override in the
derived class independent of how you
call the virtual member function:
explicitly using the this pointer
(e.g., this->method()), implicitly
using the this pointer (e.g.,
method()), or even calling some other
function that calls the virtual member
function on your this object. The
bottom line is this: even if the
caller is constructing an object of a
derived class, during the constructor
of the base class, your object is not
yet of that derived class. You have
been warned.
NOTE: Emphasis mine.
More details at the link
The only time you can do this is when something is derived from a template that is parameterised by itself:
template<typename T> class base
{
T* down_cast() throw()
{
return static_cast<Derived*>(this);
}
const T* down_cast() const throw()
{
return static_cast<const Derived*>(this);
}
public:
base()
{
down_cast()->doSomething();
}
/* … */
};
class derived : private base<derived>
{
public:
void doSomething()
{
}
};
Note that doSomething is public and not virtual.
We can static_cast to derived, because it's known that derived is the derived type.
Deriving something from a base parameterised by itself is a strange thing to be doing at the best of times. It's said that when the ATL team in microsoft used it they asked the C++ compiler team if it was valid and nobody was sure, though it is valid because template construction depends on names as follows:
First the template is available, but not used in a class. Then, the name derived available. Then it instantiates the layout of base<derived> — this requires knowledge of the member variables and virtual functions, as long as none of that depends upon knowledge of derived’s layout (pointers and references are fine) this will all go okay. Then it will create the layout of derived, and finally it will create derived’s member functions, which may include creating member functions for base<derived>. So as long as base<derived> doesn’t contain a derived member variable (base classes can never contain a member variable of a type derived from themselves) or a virtual function that requires knowledge of derived’s layout we can indeed do the dicey-looking piece of inheritance above.
This includes being able to call non-virtual public members of derived from base during construction, because it's already part of base. There are strong limitations on this. In particular, if doSomething() depends on anything constructed in derived's constructor it won't work as derived hasn't been constructed yet.
Now, is this actually a good idea? No.
A simple design solution is to use aggregation instead of inheritance.
I want to know why cant we create object if the constructor is in private section. I know that if i make a method static i can call that method using
<classname> :: <methodname(...)>;
But why can't we create object is what I don't understand.
I also know if my method is not static then also I can call function by the following:
class A
{
A();
public:
void fun1();
void fun2();
void fun3();
};
int main()
{
A *obj =(A*)malloc(sizeof(A));
//Here we can't use new A() because constructor is in private
//but we can use malloc with it, but it will not call the constructor
//and hence it is harmful because object may not be in usable state.
obj->fun1();
obj->fun2();
obj->fun3();
}
So, my question is: why can't we create an object when constructor is private?
Because it is not accessible to the program, that's what private means. If you declared a member function or variable private, you would not be able to access them either. Creating private constructors is actually a useful technique in C++, as it allows you to say that only specific classes can create instances of the type. For example:
class A {
A() {} // private ctor
friend class B;
};
class B {
public:
A * MakeA() {
return new A;
}
};
Only B can create A objects - this is useful when implementing the factory pattern.
A constructor is a special member function. It obeys the same rules as any other method when it comes to accessing it. The private access label prevents class users from invoking/accessing members declared under it.
The "new" operator needs to call the constructor, so if the constructor is private you can not execute the code "obj = new A" except inside member functions of the class A itself.
I would guess that what you have encountered is a technique that is very often used in Java (and yes I know you're writing C++, but the principle is the same) where the designer of the class wants to make sure that one and only one instance of this class will ever exist (which is called a "singleton"). To achieve this, he needs to prevent other code from creating further instances of the class using new, and making the constructor private is one way to do that. Here's a piece of Java code illustrating the technique.
public class MySingleton {
private MySingleton() {
// Private constructor, to prevent instantiation using "new"
// outside of this class.
}
public synchronized static MySingleton getInstance() {
static MySingleton instance = null;
if (instance == null) {
// I can use new here because I'm inside the class.
instance = new MySingleton();
}
return instance;
}
}
Even if you don't know Java, the syntax is similar enough to C++ that you should understand what this code is doing. The point is that the only way to get a reference to an instance of the MySingleton class elsewhere in the code is to call the static class member getInstance().
MySingleton obj = MySingleton.getInstance();
You can't instantiate your class because the constructor is private. private member variables and functions cannot be used outside of the class itself.
If you want to be able to instantiate your class, you have two options.
Option 1 is to make the constructor. This is the Right Thing to do in the vast majority of cases. Making a constructor private is a useful technique, but only when trying to accomplish specific goals.
Option 2 is to create a public static factory method. You would typically do this when Option 1 isn't an option.
class A
{
A();
public:
static A* Create() { return new A; }
void fun1();
void fun2();
void fun3();
};
int main()
{
A *obj = A::Create();
//Here we can't use new A() because constructor is in private
//but we can use malloc with it, but it will not call the constructor
//and hence it is harmful because object may not be in usable state.
obj->fun1();
obj->fun2();
obj->fun3();
}