I've got a namespace. The class is in a namespace.
namespace SALES
{
class Sales
{
...
I've created functions.
void SALES::Sales::set()
{
...
Now I'm creating an object
SALES::Sales interactive ();
but I can't get to methods.
Point my error out, please.
interactive.set(); // doesn't work
SALES::interactive.set(); // doesn't work
interactive.SALES::set(); // doesn't work
The way to access non-static members of a function is by using the member of object operator. For example,
class SomeObject {
public:
SomeObject() {}
void SayHello() { ... }
int age = 10;
};
// When calling members.
SomeObject object;
object.SayHello();
int age = object.age;
And when instantiating, use SALES::Sales interactive; or SALES::Sales interactive{}; instead. If not when you try to do it like this: SALES::Sales interactive ();, C++ will try to resolve it as a function. Now in your case, the first; interactive.set(); needs to work.
If it still doesn't work, it might have to do with the accessibility of members. Classes by default make their members private; only the friend classes and itself can access those objects. So make sure that the members are public.
Related
Lets say that I have a class with a private constructor and that class will be used to represent a single object. Lets say that I have some non-static members that I want to access without using the scope resolution operator. I've noticed that I can achieve this by creating a pointer to the class type to do so. I was wondering why can I declare pointers to that class even if the default constructor is private? Here is an example program.
// Example program
#include <iostream>
#include <string>
class OnlyOne{
public:
void Location(){
std::cout<<10<<std::endl;
}
private:
OnlyOne();
};
int main()
{
//does not work Location() is not a static member
//OnlyOne::Location();
// doesn't work because default constructor is private.
//OnlyOne one;
//one.Location();
OnlyOne* two=nullptr;
two->Location();
}
I've been looking online to see if I could find an answer and haven't been able to get what I'm looking for.
When you declare a pointer of some type, that type doesn't have to be constructible. In fact, that type doesn't even have to be complete. So, this line:
OnlyOne* two = nullptr;
is perfectly fine.
Note that this line:
two->Location();
invokes undefined behavior, since there is no object pointed at by two, and so there is no object on which you can call the Location member function.
In fact, since this type is not constructible, two could never point at a valid object. You have to provide a way to construct such an object, either by providing a public constructor, or by having a static member function, that constructs and returns such an object.
You can use singleton pttern to implement classes that have private constructor:
// Example program
#include <iostream>
#include <string>
class OnlyOne{
public:
static OnlyOne* instance() {
static OnlyOne obj;
return &obj;
}
void Location(){
std::cout<<10<<std::endl;
}
private:
OnlyOne() { }
};
int main()
{
//does not work Location() is not a static member
//OnlyOne::Location();
// doesn't work because default constructor is private.
//OnlyOne one;
//one.Location();
OnlyOne* two=OnlyOne::instance();
two->Location();
}
Found this strange compilation behavior, checked on VS2012, VS2017 and https://www.onlinegdb.com/online_c++_compiler)
Basically for private nested classes you can call public functions outside, but not public constructors.
3 questions:
what is the reasoning behind compiler letting me call func()?
if compiler lets me call func(), why I cannot call ctor?
if I cannot call ctor, how come emplace_back is able to do it?
class Outer {
struct PrivateInner {
PrivateInner() {}
void func() {}
};
public:
PrivateInner inner;
std::vector<PrivateInner> innerVect;
};
void f1()
{
Outer c;
c.inner.func(); // COMPILING, but why?
}
void f2()
{
Outer c;
c.innerVect.push_back(Outer::PrivateInner()); // NOT COMPILING, why no access to ctor if there is access to func()?
c.innerVect.emplace_back(); // COMPILING, but why? Doesn't it call Outer::PrivateInner inside?
}
As I see I still can create a (static) function createObject():
class Outer {
struct PrivateInner {
PrivateInner() {}
static PrivateInner createObject() { return PrivateInner(); }
void func() {}
};
.....
};
and then call it.
createObject() may be non-static if calling static from instances is not pure standard thing.
c.innerVect.push_back(c.inner.createObject()); // COMPILING
to "hack" compilation
Note that the nested struct PrivateInner is declared as private, so only Outer::PrivateInner is private, you can't use this name to declare variable like Outer::PrivateInner pi; without sufficient access right, but you can write it like decltype(Outer::inner) pi;.
On the other hand, its constructor and member function are public, so they can be called.
c.inner.func(); // COMPILING, but why?
func() is public, so if you have got an instance of type Outer::PrivateInner you can call func on it.
c.innerVect.push_back(Outer::PrivateInner()); // NOT COMPILING, why no access to ctor if there is access to func()?
It has nothing to do with the constructor, you just can't use the name Outer::PrivateInner here.
c.innerVect.emplace_back(); // COMPILING, but why? Doesn't it call Outer::PrivateInner inside?
The constructor is public, then it could be used to construct the object. std::vector doesn't use the name like Outer::PrivateInner directly; it uses the name specified as the template argument.
BTW: For the same reason,
c.innerVect.push_back(c.inner.createObject()); // COMPILING
but c.innerVect.push_back(Outer::PrivateInner::createObject()); won't compile.
The member is public so of course you can call its member functions. If its name is visible, then so are its own public members.
Likewise the inner class is private, so of course you can't refer to its name from outside the class. These are the basic definitions of the access control rules.
emplace_back can call the constructor because std::vector received the type as a template parameter from someone who was allowed to refer to it. The access check occurred when the template was instantiated. At that point its name was accessible.
You can call the constructor outside of the class anywhere using decltype:
Outer c;
auto this_works_too = decltype(c.inner){};
This works because you don't have to refer to it by an inaccessible name.
The access control is applied to names. That means only the name of the struct PrivateInner is restricted. The members of the struct itself have own access control. So all members of PrivateInner are public.
11 Member access control [class.access]
1 A member of a class can be
private; that is, its name can be used only by members and friends of the class in which it is declared.
...
4 Access control is applied uniformly to all names, whether the names
are referred to from declarations or expressions. ...
As you already found out, you can use the constructor (and the struct in general) if you're not using its name:
c.innerVect.push_back({});
c.innerVect.emplace_back();
even
template <typename T>
T createPrivateInner()
{
return T();
}
...
c.innerVect.push_back(createPrivateInner<decltype(Outer::inner)>());
The member "createObject()" is private. So, of course, you cannot access it. You should add some member function in public field to implement this private member.
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.
I have created a class called "ShortestTime". I have some functions within it that are not member functions, but I would like them to be able to access my member variables.
ie. I have a function that sorts a List that is a public member variable, but it doesn't have access to this member variable.
I have read something about "friend" but was unable to get this to work. How do I solve my problem?
Thanks for the help,
Robin
There are ways you could use friend to solve your problem but we would need to see sample code.
But my personal approach would be to add a function to ShortestTime that sorts your private member.
ShortestTime::SortInterals()
{
//sort private stuff
}
Is there a reason that won't work?
It completely depends on what language we are talking about here. Since you are talking about "friend" functions, I am going to assume you are talking about c++.
So basically, a friend function is just a normal function which has access to private and protected members of a class in c++. For example..
int abc(myclass a)
{
...
}
class myclass
{
int someprivatemembers;
public:
function myClass() { ... }
friend int abc(myclass);
}
Now, in the above example, the function abc will have access to someprivatemembers of object a passes to it, because it is declared as a "friend" of the class.
I have created a class called "ShortestTime". I have some functions within it that are not member functions, ...
No you don't :-). All the functions within a class are member functions by definition. You might well have some functions without the class - they would not be member functions.
but I would like them to be able to access my member variables.
ie. I have a function that sorts a List that is a public member variable, but it doesn't have access to this member variable.
Yes it does. You've said you have a public member variable List:
class X
{
public:
List identifier_;
};
All functions have access to the list, irrespective of whether they're member functions or not.
I have read something about "friend" but was unable to get this to work. How do I solve my problem?
The only situation in which you might find you need friend, and hence the one that might apply despite the statements above, is akin to...
class X
{
public:
private:
List identifier_;
};
void some_non_member_function()
{
X x;
x.identifier_; // HOW TO GET ACCESS...?
}
To grant some_non_member_function() access to a private data member, you can...
make it a friend of the class
class X
{
friend void some_non_member_function();
};
void some_non_member_function()
{
X x;
x.identifier_; // NOW OK
}
make it a member function
class X
{
public:
void some_non_member_function()
{
X x;
x.identifier_; // NOW OK
}
};
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();
}