Why the static member of the Test class in c++ is breaking encapsulation rules? - static

In the following code i have declared a test class and a static member of same type (t1) but how its data members are accessible by . operator
class Test{
int a;
static Test t1;
public:
explicit Test(int);
explicit Test();
static void set_test();
void init();
void print();
};
Test::Test():a(t1.a){}
Test::Test(int value):a(value){}
Test Test::t1(1);
void Test::init(){
a=t1.a;
}
void Test::print(){
cout<<a;
}
int main()
{
Test t;
t.print();
return 0;
}

Related

Error in Static Global Variable (C)

I have around 14 void functions that contains processes needed in order for my program to work
and all the 14 functions share the same variables so I thought of making them into static Global.
After putting <stdio.h> and all the other headers needed, I have 2 typedef struct and after that, I have put 11 static int variables and 3 static struct variables.
I have checked every single function if the struct variables have been storing the data properly, and apparently, only the void function that is first called in int main() stores the correct data into the struct variable.
When the 2nd void function is called, the global variables from the 1st void function contains no data at all.
Can anyone tell me if using the global variables for multiple functions to work is wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
typedef struct hero_data{
//... data
}hero;
typedef struct item_data{
//.... data
}item;
int totalwarrior = 0;
int totalitem = 0;
int toughtotal = 0;
int nimbletotal = 0;
int smarttotal = 0;
int skeptictotal[3] = {0};
int mystictotal[3] = {0};
int cursedtotal[3] = {0};
int brutetotal[3] = {0};
int shreddertotal[3] = {0};
int vanillatotal[3] = {0};
int typetotal = 0;
int typenum = 0;
int typechoice = 0;
int classchoice = 0;
static item curr3[10000];
static hero curr[10000];
static hero curr2[10000];
static hero smart[1][10000];
static hero nimble[1][10000];
static hero tough[1][10000];
static hero type[3][10000];
static hero skeptic[3][10000];
static hero mystic[3][10000];
static hero cursed[3][10000];
static hero brute[3][10000];
static hero shredder[3][10000];
static hero vanilla[3][10000];
static hero player1;
static hero player2;
int randbetween(int max, int min)
{
//... functioning
}
void mygets(char *name, int len, FILE * stream)
{
//... functioning
}
void available_hero(hero Class[3][10000],int typenum, int classtotal[],int classcode) //Shows the available hero based on Player's choice
{
//... functioning
}
void detail_hero(hero curr[3][10000],int classtotal[],int typenum)
{
//....functioning
}
void detail_item(item curr[10000],int whatitem)
{
//functioning
}
void pointer_conversion(hero *a, hero curr[10000], int total)
{
//....functioning
}
void TDpointer_conversion(hero *a, hero curr[3][10000], int total,int typenum)
{
//....functioning
}
void pointer_conversion2(item *a, item curr3[], int total)
{
//...functioning
}
void OD_conversion(int a[], int curr[],int typenum)
{
//....functioning
}
void TD_conversion(hero a[3][10000],hero curr[3][10000],int typetotal, int typenum, int typetotal2)
{
//....functioning
}
void TD_conversion2(hero a[3][10000],hero curr[3][10000],int typetotal[], int typenum, int typetotal2[])
{
//....functioning
}
void TD_conversion_class(hero a[1][10000],hero curr[3][10000],int classtotal[3], int typenum, int typetotal)
{
//....functioning
}
void binarycheck(int encoding, hero *dummy, int totalwarrior)
{
//....functioning
}
void check_compare_item(hero player)
{
//....functioning
}
void create_player(hero player)
{
//....functioning
}
void load_hero(hero curr[])
{
//....functioning
}
int main()
{
load_hero(curr);
load_item(curr3);
create_player(player1);
printf(""\n --> %s <---\n",player1.name); //struct hero contains the variable "name"
// Nothing gets printed while when I try to print the name within Create_player function, it works.
check_compare_item(player1);
}
When you pass a parameter by-value and changes you make to it inside the called function will not be visible in the caller (the callee is operating on a copy of the data).
Solution: send your data via pointers.
Even better: avoid static variables altogether. What benefit do they offer in this case that a regular variable does not?
If you use a global variable, why do you need to pass them to the function? You can directly use them from within your function without passing them through args. Passing the args is the problem here.
And are you using the static keyword to keep them private to the file? otherwise, avoid the static.

Forward declaration C

I have 2 header files api.h and impl.h
api.h is visible to outside files and will be included in other ".c" files. So api.h includes impl.h
api.h defines 2 structures
typedef struct
{
uint32_t att;
union
{
struct
{
void* buffer;
size_t length;
} x;
struct
{
int a, b;
} v;
} content;
}dummy;
and impl.h has some other structures and function def which uses this structure.
I tried forward declaration but it doesn't help me .
Please help .
Actually, your dummy is not a structure, but a typedef to an unnamed structure. Try naming the structure, you can then forward-declare it:
typedef struct sdummy dummy; // forward declaration
void foo(dummy *);
struct sdummy { ... }; // definition
Either reorder your code in api.h so the type declaration precedes the #include "impl.h" or give your (currently anonymous) structure itself a name like dummy, dummy_, dummy_s so you can add a forward declaration
typedef struct dummy_ dummy;
to impl.h.
If you want to hide the details of your struct then you have to define it in some .c file, let's say impl.c, so that it has internal linkage to that compilation unit. To use it you have to expose create, destroy, getter and setter functions. So a basic setup would look like this:
api.h with forward declaration for your struct
// forward declaration
typedef struct dummy* dummy_t;
// create / destroy / setter / getter (omitted)
dummy_t alloc_dummy();
void free_dummy(dummy_t);
void set_number(dummy_t, int);
void set_string(dummy_t, char*);
void print_dummy(dummy_t);
Then comes impl.c
#include "api.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct dummy {
int n;
char* s;
};
dummy_t alloc_dummy()
{
return malloc(sizeof(struct dummy));
}
void free_dummy(dummy_t dummy)
{
if(dummy) {
free(dummy->s);
free(dummy);
}
}
void set_number(dummy_t dummy, int n)
{
if(dummy) {
dummy->n = n;
}
}
void set_string(dummy_t dummy, char* s)
{
if(dummy && s) {
dummy->s = strdup(s);
}
}
void print_dummy(dummy_t dummy)
{
if(dummy) {
printf("%d, %s\n", dummy->n, dummy->s);
}
}
And finally the usage in some other C files, here main.c
#include "api.h"
int main(int argc, char** argv)
{
// struct dummy d; // error! type is unknown
// instead use the create function
dummy_t d = alloc_dummy();
// d->n = 1; // error! dereference of unknown type
// instead use the setter function
set_number(d, 1);
set_string(d, "Hello, world!");
print_dummy(d);
free_dummy(d);
return 0;
}
Ouput
1, Hello, world!

C Private Variables Get and Set methods

I am working in C, and have some variables that I don't want to be global, but I do want to have get and set methods for them that can be accessed "Globaly" outside of the file. I am used to doing this in Java, but C is very different in this manner. Basically I am looking for something that follows this pseudo Code, but I have not been able to find anywhere with examples that I might look at.
main.c
#include data.h
set(b);
datalog.c
#include data.h
get(b);
data.c
private int c;
set(b){
c = b;
}
get(c){
return c;
}
You make the variable static. When a global variable is made static, its scope is restricted to the current file.
An example is as follows:
Filename: main.c
#include <stdio.h>
#include "header.h"
extern int get();
extern void set(int);
int main()
{
set(10);
printf("value = %d \n", get());
set(20);
printf("value = %d \n", get());
set(30);
printf("value = %d \n", get());
set(40);
printf("value = %d \n", get());
return 0;
}
Filename: header.h
#include <stdio.h>
int get(void);
void set(int);
Filename: header.c
#include "header.h"
static int value = 0;
int get(void)
{
return value;
}
void set(int new_value)
{
value = new_value;
}
Output:
$ gcc -Wall -o main main.c header.h header.c
$ ./main
value = 10
value = 20
value = 30
value = 40
$
If you want private variables in c, there are a number of techniques that can approximate a private variable, but the C language actually doesn't have a "protection" concept that extends to private, public, protected (as C++ does).
C will show the name of any variable (it's a requirement in C) so you must approach it with the idea of information hiding the type of the variable (making dereferencing quite difficult).
One trick is to define the variable as an void* with the actual variable type being known in only one .c module.
/* somefile.h */
extern void* counter;
/* somefile.c */
#include "somefile.h"
int actualCounter = 0;
void* counter = &actualCounter;
/* otherfile.c */
#include "somefile.h"
// we can see "counter", but we cannot "use" it here; because we don't have access
// to the real "hidden" type of "int".
A better method is to extend this idea using the struct keyword, and make pseudo-methods, like so
/* person.h */
struct s_person;
typedef Person struct s_person;
Person* new_Person(char* name);
void delete_Person(Person* person);
void Person_setName(Person* person, char* name);
char* Person_getName(Person* person);
/* person.c */
struct s_person {
char* name;
};
Person* new_Person(char* name) {
Person* object = (Person*)malloc(sizeof(struct s_person));
// duplicate the string for more security, otherwise constructor
// could manipulate the "private" string after construction.
object->name = strdup(name);
return object;
}
void delete_Person(Person* person) {
// some implementations pass a Person** to set the reference to 0
// this implementation requires that the caller sets his own references to 0
free(person->name);
free(person);
}
void Person_setName(Person* person, char* name) {
// free the old
free(person->name);
// duplicate the new to provide "out of simulated class" modification by malicious
// name setter.
person->name = strdup(name);
}
char* Person_getName(Person* person) {
// must return a copy, otherwise one can manipulate name
// from reference provided by Person_getName(...);
return strdup(person->name);
}
/* otherfile.c */
#include "Person.h"
/* Now we can hold Person "simulated objects", but we cannot */
/* manipulate their "state" without using the C simulated object */
/* methods */
int main(int argc, char** argv) {
Person* bob = new_Person("bob");
printf("%s\n", Person_getName(bob));
delete_Person(bob);
// critical or we hold a pointer to freed memory.
bob = 0;
return 0;
}
Techniques like this have several variants, one is to have a "public struct" with a void* pointer to the "private struct". One is to include the "methods" as function pointers in the "public struct" (a step towards supporting polymorphism), one is to actually write a full and proper C++ type system which attempts to resolve things exactly as C++ would (class hierarchies, polymorphisim, late binding, information hiding, etc).
Basically, you can get some "object-oriented-ness" without too much work, but as you add more features of -ornamentation, you will add more glue code (until it is much simpler to actually use an object-oriented programming language).
You can type:
static int c;
This way, the ".o" won't export the "c" variable.
By your example, you can try using some struct with this information. A struct is like a class with only public member variables (i.e. no functions). So consider something as follows
#include <stdio.h>
typedef struct _somestruct
{
int c;
} theStruct;
int getC(theStruct* obj)
{
if(obj == NULL)
return -1;
return obj->c;
}
void setC(theStruct* obj, int val)
{
if(obj == NULL)
return;
obj->c = val;
}
int main()
{
theStruct myStruct;
setC(&myStruct, 5);
printf("%d\n", getC(&myStruct));
return 0;
}
As you can see, C works only with objects and functions. But to get a global variable across all files, try static int c = 0;
The example above is nearly as close as you can possibly get to a "java-style" convention.
static int c;
int get(void) {
return c;
}
int set(int n) {
c = n;
}
You can improve on #RageD's answer by using function pointers:
#ifndef MYCLASS_H
#define MYCLASS_H
/********************************* MyClass.h **********************************/
// Typedef function pointers for usage clarity
typedef int (*GetInt)();
typedef void (*SetInt)();
typedef struct MyClass {
int Value;
GetInt GetValue;
SetInt SetValue;
} MyClass_t;
// Make the default class accessible to other modules
extern MyClass_t new_MyClass;
#endif
/********************************* MyClass.c **********************************/
#include <stdio.h>
static int getValue(MyClass_t* obj){
if(obj == NULL)
return -1;
return obj->Value;
}
static void setValue(MyClass_t* obj, int value){
if(obj == NULL)
return;
obj->Value = value;
}
// Default "constructor" of MyClass
MyClass_t new_MyClass = {0, &getValue, &setValue};
/*********************************** main.c ***********************************/
//#include "MyClass.h"
int main(){
// Create a default instance of the class
MyClass_t myClass = new_MyClass;
// Call the private (static) Getter function --> Prints 0
printf("%d\n", myClass.GetValue(&myClass));
// Set the instance's value by the Setter function
myClass.SetValue(&myClass, 9);
// Prints 9
printf("%d\n", myClass.GetValue(&myClass));
return 0;
}

What is the data type of the name of a struct

If I wanted to make a function which takes the name of a struct as an argument, what would the method signature look like?
typedef struct Class{
} Class;
main()
{
Class *a = malloc(Class);
return instanceOf(a, Class);
}
What would the declaration of instanceOf look like?
You can't pass types to functions in C. However, you can simulate this behaviour using macros:
#define new_instance(t) (malloc(sizeof(t)))
Class *instance = new_instance(Class);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define type(x) #x
typedef struct Class{
char* type;
} Class;
Class *Class_new(){
Class *v;
v=(Class*)malloc(sizeof(Class));
v->type = "Class";
return v;
}
void Class_free(Class *a){
free(a);
}
int instanceOf(Class *a, const char* type){
return strcmp(a->type, type) == 0;
}
int main(){
Class *a = Class_new();
printf("%s\n", instanceOf(a, type(Class)) ? "YES" : "NO");
Class_free(a);
return 0;
}
// Encode and encapsulate the type within a nested structure when you create it.
struct struct_info
{
int type;
char name[32];
}
struct mystruct
{
struct struct_info;
}

Struct Inheritance in C

Can I inherit a structure in C? If yes, how?
The closest you can get is the fairly common idiom:
typedef struct
{
// base members
} Base;
typedef struct
{
Base base;
// derived members
} Derived;
As Derived starts with a copy of Base, you can do this:
Base *b = (Base *)d;
Where d is an instance of Derived. So they are kind of polymorphic. But having virtual methods is another challenge - to do that, you'd need to have the equivalent of a vtable pointer in Base, containing function pointers to functions that accept Base as their first argument (which you could name this).
By which point, you may as well use C++!
C has no explicit concept of inheritance, unlike C++. However, you can reuse a structure in another structure:
typedef struct {
char name[NAMESIZE];
char sex;
} Person;
typedef struct {
Person person;
char job[JOBSIZE];
} Employee;
typedef struct {
Person person;
char booktitle[TITLESIZE];
} LiteraryCharacter;
I like and used the idea of Typesafe inheritance in C.
For example:
struct Animal
{
int weight;
};
struct Felidae
{
union {
struct Animal animal;
} base;
int furLength;
};
struct Leopard
{
union {
struct Animal animal;
struct Felidae felidae;
} base;
int dotCounter;
};
Usage:
struct Leopard leopard;
leopard.base.animal.weight = 44;
leopard.base.felidae.furLength = 2;
leopard.dotCounter = 99;
If your compiler supports anonymous structs, you can do this:
typedef struct Base
{
// base members
} Base_t;
typedef struct
{
struct Base; //anonymous struct
// derived members
} Derived_t;
This way, base stuct members can be acessed directly, which is nicer.
If you want to use some gcc magic (that I would assume would work with Microsoft's C compiler) you can do something like:
struct A
{
int member1;
};
struct B
{
struct A;
int member2;
}
With gcc you can compile this with -fms-extensions (Allows for unnamed struct members like Microsofts compiler does). This is similar to the solution given by Daniel Earwicker except that it allows you to access memeber1 on a struct B instance. i.e B.member1 instead of B.A.member1.
This is probably not the most portable approach and will not work if using a C++ compiler (different language semantics mean that it is redeclaring/defining struct A instead of instantiating it).
If however you live in the gcc/C land only it will work and do exactly what you want.
This works compiling with -fms-extensions
Diagram image
main.c
#include "AbstractProduct.h"
#include "Book.h"
#include "Product.h"
#include "TravelGuide.h"
/***********************/
int main() {
Product p = Product_new();
p.set_id(&p, 2);
p.set_name(&p, "name2");
p.set_description(&p, "description2");
p.set_price(&p, 2000);
p.display(&p);
TravelGuide tg = TravelGuide_new();
tg.set_id(&tg, 1);
tg.set_name(&tg, "name1");
tg.set_description(&tg, "description1");
tg.set_price(&tg, 1000);
tg.set_isbn(&tg, "isbn1");
tg.set_author(&tg, "author1");
tg.set_title(&tg, "title1");
tg.set_country(&tg, "country1");
tg.display(&tg);
}
AbstractProduct.c
#include "AbstractProduct.h"
/*-------------------------------*/
static void set_id(AbstractProduct *this, int id) {
this->id = id;
}
/*-------------------------------*/
static void set_name(AbstractProduct *this, char *name) {
strcpy(this->name, name);
}
/*-------------------------------*/
static void set_description(AbstractProduct *this, char *description) {
strcpy(this->description, description);
}
/*-------------------------------*/
static int get_id(AbstractProduct *this) {
return this->id;
}
/*-------------------------------*/
static char *get_name(AbstractProduct *this) {
return this->name;
}
/*-------------------------------*/
static char *get_description(AbstractProduct *this) {
return this->description;
}
/*-------------------------------*/
static void display(AbstractProduct *this) {
printf("-AbstractProduct- \n");
printf("id: %d\n", this->get_id(this));
printf("name: %s\n", this->get_name(this));
printf("description: %s\n", this->get_description(this));
printf("\n");
}
/*-------------------------------*/
void AbstractProduct_init(AbstractProduct *obj) {
obj->set_id = set_id;
obj->set_name = set_name;
obj->set_description = set_description;
obj->get_id = get_id;
obj->get_name = get_name;
obj->get_description = get_description;
obj->display = display;
}
/*-------------------------------*/
AbstractProduct AbstractProduct_new() {
AbstractProduct aux;
AbstractProduct_init(&aux);
return aux;
}
AbstractProduct.h
#ifndef AbstractProduct_H
#define AbstractProduct_H
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/***********************/
typedef struct AbstractProduct{
int id;
char name[1000];
char description[1000];
void (*set_id)();
void (*set_name)();
void (*set_description)();
int (*get_id)();
char *(*get_name)();
char *(*get_description)();
void (*display)();
} AbstractProduct;
AbstractProduct AbstractProduct_new();
void AbstractProduct_init(AbstractProduct *obj);
#endif
Book.c
#include "Book.h"
/*-------------------------------*/
static void set_isbn(Book *this, char *isbn) {
strcpy(this->isbn, isbn);
}
/*-------------------------------*/
static void set_author(Book *this, char *author) {
strcpy(this->author, author);
}
/*-------------------------------*/
static void set_title(Book *this, char *title) {
strcpy(this->title, title);
}
/*-------------------------------*/
static char *get_isbn(Book *this) {
return this->isbn;
}
/*-------------------------------*/
static char *get_author(Book *this) {
return this->author;
}
/*-------------------------------*/
static char *get_title(Book *this) {
return this->title;
}
/*-------------------------------*/
static void display(Book *this) {
Product p = Product_new();
p.display(this);
printf("-Book- \n");
printf("isbn: %s\n", this->get_isbn(this));
printf("author: %s\n", this->get_author(this));
printf("title: %s\n", this->get_title(this));
printf("\n");
}
/*-------------------------------*/
void Book_init(Book *obj) {
Product_init((Product*)obj);
obj->set_isbn = set_isbn;
obj->set_author = set_author;
obj->set_title = set_title;
obj->get_isbn = get_isbn;
obj->get_author = get_author;
obj->get_title = get_title;
obj->display = display;
}
/*-------------------------------*/
Book Book_new() {
Book aux;
Book_init(&aux);
return aux;
}
Book.h
#ifndef Book_H
#define Book_H
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Product.h"
/***********************/
typedef struct Book{
Product;
char isbn[1000];
char author[1000];
char title[1000];
void (*set_isbn)();
void (*set_author)();
void (*set_title)();
char *(*get_isbn)();
char *(*get_author)();
char *(*get_title)();
// void (*display)();
} Book;
Book Book_new();
void Book_init(Book *obj);
#endif
Product.c
#include "Product.h"
/*-------------------------------*/
static void set_price(Product *this, double price) {
this->price = price;
}
/*-------------------------------*/
static double get_price(Product *this) {
return this->price;
}
/*-------------------------------*/
static void display(Product *this) {
AbstractProduct p = AbstractProduct_new();
p.display(this);
printf("-Product- \n");
printf("price: %f\n", this->get_price(this));
printf("\n");
}
/*-------------------------------*/
void Product_init(Product *obj) {
AbstractProduct_init((AbstractProduct*)obj);
obj->set_price = set_price;
obj->get_price = get_price;
obj->display = display;
}
/*-------------------------------*/
Product Product_new() {
Product aux;
Product_init(&aux);
return aux;
}
Product.h
#ifndef Product_H
#define Product_H
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "AbstractProduct.h"
/***********************/
typedef struct Product{
AbstractProduct;
double price;
void (*set_price)();
double (*get_price)();
// void (*display)();
} Product;
Product Product_new();
void Product_init(Product *obj);
#endif
TravelGuide.c
#include "TravelGuide.h"
/*-------------------------------*/
static void set_country(TravelGuide *this, char *country) {
strcpy(this->country, country);
}
/*-------------------------------*/
static char *get_country(TravelGuide *this) {
return this->country;
}
/*-------------------------------*/
static void display(TravelGuide *this) {
Book b = Book_new();
b.display(this);
printf("-TravelGuide- \n");
printf("country: %s\n", this->get_country(this));
printf("\n");
}
/*-------------------------------*/
void TravelGuide_init(TravelGuide *obj) {
Book_init((Book*)obj);
obj->set_country = set_country;
obj->get_country = get_country;
obj->f = obj->display;
obj->display = display;
}
/*-------------------------------*/
TravelGuide TravelGuide_new() {
TravelGuide aux;
TravelGuide_init(&aux);
return aux;
}
TravelGuide.h
#ifndef TravelGuide_H
#define TravelGuide_H
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Book.h"
/***********************/
typedef struct TravelGuide{
Book;
char country[1000];
void (*f)();
void (*set_country)();
char *(*get_country)();
// void *(*display)();
} TravelGuide;
TravelGuide TravelGuide_new();
void TravelGuide_init(TravelGuide *obj);
#endif
Makefile
.PHONY: clean
define ANNOUNCE_BODY
***********************************************
************ start make **************
***********************************************
endef
all:
$(info $(ANNOUNCE_BODY))
clear;
if [ -f binary/main ]; then rm binary/main; fi;
# compiler
gcc $(INC) -c -fms-extensions main.c -o binary/main.o
gcc $(INC) -c -fms-extensions AbstractProduct.c -o binary/AbstractProduct.o
gcc $(INC) -c -fms-extensions Product.c -o binary/Product.o
gcc $(INC) -c -fms-extensions Book.c -o binary/Book.o
gcc $(INC) -c -fms-extensions TravelGuide.c -o binary/TravelGuide.o
# linker
gcc binary/main.o \
binary/AbstractProduct.o \
binary/Product.o \
binary/Book.o \
binary/TravelGuide.o \
-o \
binary/main
You can do the above mentioned
typedef struct
{
// base members
} Base;
typedef struct
{
Base base;
// derived members
} Derived;
But if you want to avoid pointer casting, you can use pointers to a union of Base and Derived.
A slight variation to the answer of anon (and others' similar). For one level deep inheritance one can do the following:
#define BASEFIELDS \
char name[NAMESIZE]; \
char sex
typedef struct {
BASEFIELDS;
} Person;
typedef struct {
BASEFIELDS;
char job[JOBSIZE];
} Employee;
typedef struct {
BASEFIELDS;
Employee *subordinate;
} Manager;
This way the functions accepting pointer to Person, will accept pointer to Employee or Manager (with casting), same as in other answers, but in this case the initialisation will be natural as well:
Employee e = {
.name = "...";
...
};
vs
# as in anon's answer
Employee e = {
.person.name = "...";
...
};
I believe this is how some popular projects do that (eg. libuv)
UPDATE: also there are some good examples of similar (but not the same) concept in libsdl events implementation using structs and unions.
C is not an object-oriented language and hence has no inheritance.
You can simulate it, but you can't really inherit.
No, you cant.
imo the best approach to OOP in C is using ADT.
No you cannot. C does not support the concept of inheritance.

Resources