static stuff

J

Jon Slaughter

Is there any way to declare a member of a base class to make the itself in
the derived class to be static?

i.e., I have two classes

class Base
{

protected:
char *name;

};

class Derived1 : Base
{
public:
Get_Name(char *s)
{
strcpy(s,name); // or whatever
}

};

class Derived2 : Base
{
public:
Get_Name(char *s)
{
strcpy(s,name); // or whatever
}

};

the problem is that each derived object allocates a name pointer and for my
application each object of the derived class will all have the same name(the
name represents the name of the class)


but if I did this

class C
{
private:
static char name[] = "C Class";
public
Get_Name(char *s)
{
strcpy(s, C::name);
}
}

class Q
{
private:
static char name[] = "Q Class";
public
Get_Name(char *s)
{
strcpy(s, Q::name);
}
}

then there is only one name pointer for all the objects of the C class...
but he problem is that I will have many different types of classes that all
inherent from a base class and I want to be able to differentiate them by
there name... but I don't want to have to declare a static variable in each
of the different class declerations(cause lets say I forget one).

I'm pretty sure that if I do this:

class Base
{

protected:
static char *name;

};

class Derived1 : Base
{
public:
Derived1()
{
strcpy("Derived1 class", Base::name); // or is it Derived1::name?
}
Get_Name(char *s)
{
strcpy(s,name); // or whatever
}

};


class Derived2 : Base
{
public:
Derived2()
{
strcpy("Derived2 class", Base::name); // or is it Derived2::name?
}
Get_Name(char *s)
{
strcpy(s,name); // or whatever
}

};

that both the derived classes will be stepping over each others shoes.

Basicaly I want to have some static members of derived classes but force
them to be declared and to be static in an elegant way(and not by declaring
the member static in all those classes I will have to create)


Also I am wondering that if I declare an array as const does that gaurantee
that it cannot be changed? (i.e. does the compiler stick it in some type of
read only memory or something?)

Thanks,
Jon
 
M

Maxim Yegorushkin

On Thu, 30 Jun 2005 08:45:26 +0400, Jon Slaughter

[]
Basicaly I want to have some static members of derived classes but force
them to be declared and to be static in an elegant way(and not by
declaring
the member static in all those classes I will have to create)

Just think of inheritance in another way. Make your derived classes base
classes that are used for generation of "concrete" derived classes.
Somethink like this:

#include <string>
#include <iostream>

template<class B, char const* Name>
struct decorator : B
{
// forwarding ctors if needed
decorator() {}
template<class T1> decorator(T1 const& t1) : B(t1) {}
template<class T1, class T2> decorator(T1 const& t1, T2 const& t2) :
B(t1, t2) {}
// ...

std::string name() const { return Name; }
};

struct A_impl {};
struct B_impl {};

extern char const A_name[] = "A class";
extern char const B_name[] = "B class";

typedef decorator<A_impl, A_name> A;
typedef decorator<B_impl, B_name> B;

int main()
{
A a;
std::cout << a.name() << std::endl;
B b;
std::cout << b.name() << std::endl;
}
 
J

Jon Slaughter

Maxim Yegorushkin said:
On Thu, 30 Jun 2005 08:45:26 +0400, Jon Slaughter

[]
Basicaly I want to have some static members of derived classes but force
them to be declared and to be static in an elegant way(and not by
declaring
the member static in all those classes I will have to create)

Just think of inheritance in another way. Make your derived classes base
classes that are used for generation of "concrete" derived classes.
Somethink like this:

#include <string>
#include <iostream>

template<class B, char const* Name>
struct decorator : B
{
// forwarding ctors if needed
decorator() {}
template<class T1> decorator(T1 const& t1) : B(t1) {}
template<class T1, class T2> decorator(T1 const& t1, T2 const& t2) :
B(t1, t2) {}
// ...

std::string name() const { return Name; }
};

struct A_impl {};
struct B_impl {};

extern char const A_name[] = "A class";
extern char const B_name[] = "B class";

typedef decorator<A_impl, A_name> A;
typedef decorator<B_impl, B_name> B;

int main()
{
A a;
std::cout << a.name() << std::endl;
B b;
std::cout << b.name() << std::endl;
}

but this looks like it will store Name for each object created?

I will have many objects with the same class name

like I will have

typedef decorator<A_impl, A_name> A1;
typedef decorator<A_impl, A_name> A2;
typedef decorator<A_impl, A_name> A3;
typedef decorator<A_impl, A_name> A4;

so will the template store A_name 4 times(or atleast a pointer in each
object?) or will all references to A_name refer to only one location? (heh,
I will have to study up on templates to see what is exactly going on here...
I'm only familiar with the very basics of them(since I haven't programmed in
a very very long time)

Thanks

Jon
 
M

Maxim Yegorushkin

On Thu, 30 Jun 2005 09:22:26 +0400, Jon Slaughter

[]
but this looks like it will store Name for each object created?

No, Name is a pointer and it is not stored as a data member in objects,
rather it's hardcoded in code where you refer to it.
I will have many objects with the same class name

like I will have

typedef decorator<A_impl, A_name> A1;
typedef decorator<A_impl, A_name> A2;
typedef decorator<A_impl, A_name> A3;
typedef decorator<A_impl, A_name> A4;

Here you did not declare any objects, rather you declared A1..4 to be
aliases for the same type decorator said:
so will the template store A_name 4 times(or atleast a pointer in each
object?) or will all references to A_name refer to only one location?

As I said the pointer is hardcoded. The string literal used to initialized
the pointer has external linkage and static storage duration, which means
there will be only one instance of the literal in your program.
 
J

Jon Slaughter

Maxim Yegorushkin said:
On Thu, 30 Jun 2005 09:22:26 +0400, Jon Slaughter

[]
but this looks like it will store Name for each object created?

No, Name is a pointer and it is not stored as a data member in objects,
rather it's hardcoded in code where you refer to it.
I will have many objects with the same class name

like I will have

typedef decorator<A_impl, A_name> A1;
typedef decorator<A_impl, A_name> A2;
typedef decorator<A_impl, A_name> A3;
typedef decorator<A_impl, A_name> A4;

Here you did not declare any objects, rather you declared A1..4 to be
aliases for the same type decorator<A_impl, A_name>.

heh yeah... I see now(not sure what I said that)(I think I understand the
code now for the most part... maybe it was just to late last night).
As I said the pointer is hardcoded. The string literal used to initialized
the pointer has external linkage and static storage duration, which means
there will be only one instance of the literal in your program.

--

ok, I think I see why. when you do "return name" in the template it is and
the template is used to create the class it just returns the address of that
string which was declared only once and has only one "instance".

Now I have a new question. I figured that, say, if I create a bunch of char
pointers and then all initalize them to the same string..

maybe something like

strcpy(p1, "Note")

then somewhere else

strcpy(p2, "Note")

etc...

is the compiler going to make one instance of Note? i.e. does it compact all
string literals in the program into a table and remove identical strings?

Thanks

Jon
 
M

Maxim Yegorushkin

On Thu, 30 Jun 2005 18:11:52 +0400, Jon Slaughter

[]
Now I have a new question. I figured that, say, if I create a bunch of
char pointers and then all initalize them to the same string..
maybe something like

strcpy(p1, "Note")

then somewhere else

strcpy(p2, "Note")

The you'd probably get a SIGSEGV trying to strcpy to an uninitialized
pointer.

char const* p1 = "note";
char const* p2 = "note";

is the compiler going to make one instance of Note? i.e. does it compact
all
string literals in the program into a table and remove identical strings?

This is done in the linker. Modern GNU and M$ linkers do that.
 
J

Jon Slaughter

Maxim Yegorushkin said:
On Thu, 30 Jun 2005 18:11:52 +0400, Jon Slaughter

[]
Now I have a new question. I figured that, say, if I create a bunch of
char pointers and then all initalize them to the same string..
maybe something like

strcpy(p1, "Note")

then somewhere else

strcpy(p2, "Note")

The you'd probably get a SIGSEGV trying to strcpy to an uninitialized
pointer.

char const* p1 = "note";
char const* p2 = "note";

heh, yeah, but was just some C++ pseudo code ;)
This is done in the linker. Modern GNU and M$ linkers do that.

Ok... so at most I would just be wasting a pointer for storage of those
address... though I think its better to use the literal address(instead of a
pointer to the literal address) like you have done.

Thanks again.
Jon
 
J

Jon Slaughter

Maxim Yegorushkin said:
On Thu, 30 Jun 2005 08:45:26 +0400, Jon Slaughter

[]
Basicaly I want to have some static members of derived classes but force
them to be declared and to be static in an elegant way(and not by
declaring
the member static in all those classes I will have to create)

Just think of inheritance in another way. Make your derived classes base
classes that are used for generation of "concrete" derived classes.
Somethink like this:

#include <string>
#include <iostream>

template<class B, char const* Name>
struct decorator : B
{
// forwarding ctors if needed
decorator() {}
template<class T1> decorator(T1 const& t1) : B(t1) {}
template<class T1, class T2> decorator(T1 const& t1, T2 const& t2) :
B(t1, t2) {}
// ...

std::string name() const { return Name; }
};

struct A_impl {};
struct B_impl {};

extern char const A_name[] = "A class";
extern char const B_name[] = "B class";

typedef decorator<A_impl, A_name> A;
typedef decorator<B_impl, B_name> B;

int main()
{
A a;
std::cout << a.name() << std::endl;
B b;
std::cout << b.name() << std::endl;
}

ok, I am wondering why you went through all the trouble of declaring the
template to have a base class?

I came up with this example:

template<char const *Name>
class test
{
public:
char const *Get_Name()
{
return Name;
}
}

// must be extern for some reason
extern char const Name[] = "Name";


int main()
{
test<Name> t;

// This line is invalid... not sure exactly why.. I suppose the compiler
doesn't internally treat "Name" as a char const variable or something and so
it doesn't really have an address(i..e its not treated as a pointer but a
literal I suppose)
test<"Name"> t;

cout << t.Get_Name();
}


now, can't I use that template in the creation of my new class(which would
have been my derived class before)? I mean
can't I do something like

class new_test : test<Name>
{

blah...
}

? I mean maybe not valid C++ code but surely I don' thave to really derive a
new class... I just copy the stuff in the template to the new class... so it
would look something like:

class new_test : test<Name>
{
public:
char const *Get_Name()
{
return Name;
}

blah...
}


I mean surely C++ has a way to extend a class from another template without
deriving it from an object created by the template? (i.e. I don't think I
will really need a base class if I use a template like that because the
template can be included directly in the class and act part of that class?)?

Thanks again.

Jon
 
M

Maxim Yegorushkin

On Fri, 01 Jul 2005 00:37:47 +0400, Jon Slaughter

[]
ok, I am wondering why you went through all the trouble of declaring the
template to have a base class?

You can have the template as a base class as well.
I came up with this example:

template<char const *Name>
class test
{
public:
char const *Get_Name()
{
return Name;
}
}

// must be extern for some reason
extern char const Name[] = "Name";


int main()
{
test<Name> t;

// This line is invalid... not sure exactly why.. I suppose the compiler
doesn't internally treat "Name" as a char const variable or something
and so
it doesn't really have an address(i..e its not treated as a pointer but a
literal I suppose)
test<"Name"> t;

cout << t.Get_Name();
}

a semicolon after test said:
now, can't I use that template in the creation of my new class(which
would
have been my derived class before)? I mean
can't I do something like

class new_test : test<Name>
{

blah...
}

? I mean maybe not valid C++ code but surely I don' thave to really
derive a
new class... I just copy the stuff in the template to the new class...
so it
would look something like:

class new_test : test<Name>
{
public:
char const *Get_Name()
{
return Name;
}

blah...
}

Yes, you can do it as well.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top