i have two classes (non-static) A & (static) B.
I am trying to store Object A into B so that i can use its functions in funcB().
However i do know that static classes cannot store non-static variables & functions. is there anyway to get pass this rather than converting Class A into a static class?
class A
{
public:
A();
void funcA();
private:
int A;
};
class B
{
public:
B(A *objA);
static void funcB();
private:
A *objA;
};
edit:
I stated static class to make it easier to explain. i did not know the correct term.
So the question is actually: How do i use a non-static member from a static function?
You can not access anything that is specific to an instance of a class from a static function by itself. A static function has no "this" pointer (the compiler passes a pointer to the instance of the object calling the function for non-static functions). You can get around this by passing a pointer to the object you want to modify, but then why are you using a static function? My advice would be to avoid what it seems like you are trying to do, but I provided 2 ways to do it below (as a good learning example).
See below for an example of using
#include <iostream>
using namespace std;
class A
{
public:
A(int value) : a(value){}
void funcA();
public:
int a;
};
class B
{
public:
B()
{
objA = new A(12);
}
void funcB2()
{
B::funcB(*objA);
}
static void funcB(A const & value)
{
cout << "Hello World! " << value.a << endl;
}
private:
A *objA;
};
int main()
{
A a(10);
B::funcB(a);
B b;
b.funcB2();
return 0;
}
I think you just should not make design like this. A static function is initialized when the non-static members are not ready. You said "the class A, links to many other classes and has stored many other information. Class B on the other hand, has to be static due to some windows API threading condition." . In this case, can you change your design and turn A into static class?
Related
We have classes A, B and C, all of which need access to a static variable staticVariable in class D.
Moreover, class A needs to have an instance of classes B and C like this:
class A{
public:
B instanceB;
C instanceC;
};
Class D hold the static variable of object type T:
class D{
public:
D() {
staticVariable.init();
};
static T staticVariable;
};
In the example classes B and C can be empty placeholder classes:
class B{
};
class C{
};
The main function creates an instance of A:
int main(){
A a;
/*...*/
}
Again, classes A, B and C need access to staticVariable. I've tried multiple approaches including inheritance and friend functions, however I always get dependency issues or linker errors I don't quite understand:
Error LNK2001 unresolved external symbol "public: static class T
D::staticVariable" (?window#D##2VT#sf##A) SortingAlgorithms
C:\Users\Dusan\source\repos\SortingAlgorithms\SortingAlgorithms\B.obj
is being reported in .obj files of classes A, B and C.
I'm not sure if I need an instance of D in main.
How do I implement this error-free?
And how do you do it for static objects that call a function for initialization?
I meant if the function is of the same class as the object you're trying to initialize, and is non-static, I can't seem to be able to call staticVariable.init();
I'm not sure if I need an instance of D in main.
You don't. static variables are global, they are shared by all the instances of the same class and you don't need to instantiate a class to be able to use such variables so they must be initialized regardless of class instantiation. That being the case they need to be initialized outside the class.
How do I implement this error-free?
Something like:
class B{};
class C{};
class A{
public:
B instanceB;
C instanceC;
};
class D{
public:
D(){};
static int staticVariable;
};
int D::staticVariable = 10; //<-- here, outside the class
int main()
{
//no instance of D needed
std::cout << D::staticVariable; // prints 10
D::staticVariable++;
std::cout << D::staticVariable; // prints 11
}
And how do you do it for static objects that call a function for initialization?
I meant if the function is of the same class as the object you're trying to initialize, and is non-static, I can't seem to be able to call staticVariable.init();
It's the same principle, you declare the object static within the class and initialize it outside:
class A{
public:
void init(){std::cout << "Do Something";} //non-static method
};
class D{
public:
static A obj; //declare
};
A D::obj{}; //<-- initialize outside the class
int main()
{
D::obj.init(); // prints 'Do Something'
}
// in D.hpp
class D {
public:
D() { ... }; // staticVariable is static, so the ctor has no business initializing it
void init();
static int staticVariable;
static D staticD;
};
// in D.cpp
#include "D.hpp"
int D::staticVariable = 10;
// Immediatly invoked initializing lambda expression
D D::staticD = []{ D tmp; tmp.init(); return tmp; }();
I have the following class
class A {
private:
B b;
public:
A();
}
class B {
public:
void foo();
void bar();
void foz();
........
}
B has a lot of methods. Sometimes is needed for a "customer" of class A to use method of class B. I could return a reference of B, but in this case I should return a const reference because returning a non-const reference of a private object is not good programming. If the reference is const, foo, bar and so on can't be called because they aren't const. So the only "clean" way seems to recreate the same interfaces in A using delegation to B. But this approach is not really good because I should recreate all the interfaces in A. As alternative I could set B as public in A, but it seems "strange" to me. What should I do in this case?
That is mainly an encapsulation question, and what you want to advertise in the public interface of class A.
If class B is also a public class - read can normally be used by users of class A and not a class internal to a library or framework - and if you want the existence of a B subobject to exist in the public documentation of class A and if you want to allow any operation on the B object, you can safely provide a getter.
If any of the above conditions is false, then the getter would break encapsulation and you would better define delegating methods in class A.
Depending on the general design, it could make sense to declare an interface class (say C) with only the methods that you want to allow from class A, and have B a subclass from C. Then you could safely declare a getter returning a reference on a C object:
class C {
public:
void foo(); // optionally virtual or pure virtual...
void bar();
void foz();
};
class B: public C {
.... // other members not relevant for what is public for A users
};
class A {
private:
B b;
public:
A();
C& getB() {
return b;
}
};
Solution 1. You create a getb() and return reference to B. Its not bad programming in you case particularly.
Solution 2. Create interface function for each corresponding function of b and call them.
void A::foo()
{
b.foo();
}
You can make the data member protectedinstead of private. Documentation says that protected members are not as private as private members, which are accessible only to members of the class in which they are declared, but they are not as public as public members, which are accessible in any function. protectedmembers (be they data members of method members) serve the role you're looking for : they are not accessible from everywhere (safe coding practices), but you can still manage them in clean ways when it makes sense :
If class A has an attribute of type B, is has access to B's
protected and publicmembers
friendfunctions can access both protected and publicmembers of a class they are friend with.
When preceding the name of a base class, the protected keyword specifies that the public and protected members of the base class are protected members of its derived classes.
Here, you're interested by the first item of the list : you can access B' methods from A; BUT B has still safeguards.
When I run the following code (adapted from your code) :
#include <iostream>
using std::cout;
using std::endl;
class B {
public:
void foo() { cout << "foo" << endl; };
void bar() { cout << "bar" << endl; };
void foz() { cout << "foz" << endl; };
};
class A {
protected: // <===== THIS IS THE SIGNIFICANT BIT
B b;
public:
A() {
b.foo();
b.bar();
b.foz();
cout << "A constructor" << endl;
};
};
int main(int argc, char** argv) {
A myA;
return 0;
}
I get the following console output :
foo
bar
foz
A constructor
Which shows that I can access B's methods from A.
Disclaimer: I'm a long time C programmer moving into C++, so it's very likely/possible there is a better way to do this.
I would like to create a class A with 1 to N members of class B. In most cases, I'm fine calling class B's member functions. However, in some cases I would like to override a member function in class B. Is there an elegant way to do this without having to create a derived class from class B every time?
Here is an example:
using namespace std;
#include <iostream>
class B
{
public:
void print();
};
void B::print()
{
cout << "B::print" << endl;
}
class A
{
public:
B b;
B bprime;
};
int main()
{
A a;
a.b.print();
a.bprime.print();
return 0;
}
Is there a way to override the print() function in bprime or otherwise change it? In C, I would have left class B as a struct and used function pointers, but I'd like to avoid that here.
You can use std::function to simulate polymorphism.
class B
{
public:
std::function<_FUNCTION_SIGNATURE_HERE_> print;
};
then you can always override print member in an instance of B
a.bprime.print = SomeOTherFunctionWithSameSignature;
and from this moment on bprime will behave as if it was a different subclass in a hierarchy. Everything will work the same, except this particular function you changed.
Of course you will have to set initial behavior of print member in your constructor.
I was wondering how I would go about using a variable of a specific instance of a class within a function of another class.
To provide an example of what I'm trying to do, say I've 3 classes a,b and c. Class c inherits from class b, and a single instance of b and c are called within a method in class a and b respectively. How would I go about using the variable of int pos (see below) within a specific instance of class a in class c?
class a
{
private:
void B(); //Calls an instance of class c
int pos; //Variable that I want to use in c
};
class b : public c
{
private:
void C(); //Calls an instance of class b
};
class c
{
private:
void calculate(int _pos); //Method which requires the value of pos from class a
};
Help would be greatly appreciated, thank you!
Your code sample doesn't make much sense for me, and you aren't really clear what you want to achieve.
"How would I go about using the variable of int pos (see below) within a specific instance of class a in class c?"
Fact is you can't access any private class member variables from other classes.
Since class c and class b aren't declared as friend for class a, these cannot access the pos member from a::pos directly. You have to pass them a reference to class a; at some point, and provide public (read access) to pos with a getter function :
class a {
int pos; //Variable that I want to use in c
public:
int getPos() const { return pos; } // <<< let other classes read this
// property
};
And use it from an instance of class c() like e.g. (constructor):
c::c(const a& a_) { // <<< pass a reference to a
calculate(a_.getPos());
}
I'm not sure if I understand your problem, but if you want to access a member of a class instance from a non-friend non-base class, that member must be exposed of there must be some function that access it. For example:
class a
{
public:
int getPos() const { return pos; }
private:
void B(); //Calls an instance of class c
int pos; //Variable that I want to use in c
};
I realy don't understand why it works, but below code shows an example of calling private method from the world without any friend classes:
class A
{
public:
virtual void someMethod(){
std::cout << "A::someMethod";
}
};
class B : public A
{
private:
virtual void someMethod(){
std::cout << "B::someMethod";
}
};
int main(){
A* a = new B;
a->someMethod();
}
outputs:
B::someMethod
Doesn't it violates encapsulation rules in C++? For me this is insane. The inheritance is public, but the access modifier in derived class is changed to private, thus the someMethod() in class B is private. So in fact, doing a->someMethod(), we are directly calling a private method from the world.
Consider the following code, a modification of the code in the original question:
class A
{
public:
virtual void X(){
std::cout << "A::someMethod";
}
};
class B : public A
{
private:
virtual void Y(){
std::cout << "B::someMethod";
}
};
int main(){
A* a = new B;
a->X();
}
It's easy to understand that it's legit to call X(). B inherits it from A as a public member. Theoretically if X() would call Y() this would be legit as well of course, although this is not possible because X() is declared in A which doesn't know Y(). But actually this is the case if X = Y, i.e. if both methods have the same name.
You may think of it as "B inherits a public method from A, that calls a private method (of B) with the same name".
a is a pointer to an A object where the method is public, so this is not a violation. Since, you have used virtual, the VTABLE is taken into account and you get the output as B::someMethod.
For me this is quite simple.
As you are allowed to asign any dynamic type inheritance of a class to an object of the parrent-class it would be vise versa.But as you are assigning the Child to its parrent object pointer this could be bad as if the class of B where bigger as A.
If a program attempts to access the stored value of an object through an lvalue of other than one of the following types the behavior is undefined:
the dynamic type of the object,
a cv-qualified version of the dynamic type of the object,
a type that is the signed or unsigned type corresponding to the dynamic type of the object,
a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union),
a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
a char or unsigned char type.
So as in your code you aren't fitting this conditions, but as B has the sime size as A, it would be possible to run it. But it is undefined behavior.
And as you creat a new B the memory block a is pointing to has the method of printing B and not A.
The access control specifiers (public, protected and private) do not apply to member functions or data members. They apply to member function and data member names. And that works. If you can refer to the member without the name, you can access it.
That's precisely what's happening here. You're calling B::someMethod, but you're calling it using the name A::someMethod, which is public. No problem.
You're suggesting a private member function shouldn't be callable from outside of the class (disregarding friends for the moment). How would your desired semantics work in the following case?
Shared library hider:
hider.h:
typedef void (*FuncType)();
class Hider {
private:
static void privFunc();
public:
static void pubFunc();
FuncType getFunction() const;
};
hider.cpp
#include <cstdlib>
#include <iostream>
#include "hider.h"
void Hider::privFunc() {
std::cout << "Private\n";
}
void Hider::pubFunc() {
std::cout << "Public\n";
}
FuncType Hider::getFunction() const {
if (std::rand() % 2) {
return &pubFunc;
} else {
return &privFunc;
}
}
Application using library hider
#include "hider.hpp"
int main()
{
Hider h;
FuncType f = h.getFunc();
f();
}
What about the call to f()? Should it fail at runtime 50% of the time with some form of access control violation?
As suggested by DyP in the comments, a more realistic scenario is the well-known "template method" design pattern:
class Container
{
public:
void insert(const Item &item) {
preInsert();
data.insert(item);
postInsert();
}
private:
std::vector<Item> data;
virtual void preInsert() = 0;
virtual void postInsert() = 0;
};
class ThreadSafeContainer : public Container
{
private:
std::mutex m;
virtual void preInsert() {
m.lock();
}
virtual void postInsert() {
m.unlock();
}
};
Your semantics would mean this code wouldn't compile.