 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
IronGoth Guest
|
Posted: Tue Jul 19, 2005 9:28 am Post subject: Accessing derived static member variable? |
|
|
Here's an interesting question...
I'd like to do this:
class Person
{
protected:
virtual static std::string citizenship; //yeah, I know.
protected:
Report() { std::cout << "I am " << citizenship << std::endl; }
}
class Frenchman : public Person
{
protected:
static std::string citizenship;
}
class Englishman : public Person
{
protected:
static std::string citizenship;
}
std::string Frenchman::citizenship = std::string("French");
std::string Englishman::citizenship = std::string("English");
int main(argc, argv) // can't be arsed to look it up
{
Englishman Bertie, Rupert, Jasper;
Frenchman Jean_Guy, Jean_Paul, Jean_Marie;
Bertie.Report(); // "I am English"
Jean_Guy.Report(); // "I am French"
}
Now, I want citizenship to be STATIC that way I don't have thirty
million instances of the string "French"
I also want to have the code common to all citizenships without having
the exact same function in every single Person class.
I am very overtired but also puzzled. I was hoping there would be a way
to do this.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Maxim Yegorushkin Guest
|
Posted: Tue Jul 19, 2005 11:31 am Post subject: Re: Accessing derived static member variable? |
|
|
On Tue, 19 Jul 2005 13:28:27 +0400, IronGoth <darkpast2000 (AT) yahoo (DOT) com>
wrote:
| Quote: | Here's an interesting question...
I'd like to do this:
class Person
{
protected:
virtual static std::string citizenship; //yeah, I know.
|
Just replace it with a virtual function:
virtual std::string get_citizenship() const = 0;
| Quote: | protected:
Report() { std::cout << "I am " << citizenship << std::endl; }
|
Report() { std::cout << "I am " << this->get_citizenship() <<
std::endl; }
| Quote: | };
class Frenchman : public Person
{
protected:
static std::string citizenship;
|
std::string get_citizenship() const { return "French"; }
--
Maxim Yegorushkin
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Julien Lamy Guest
|
Posted: Tue Jul 19, 2005 11:32 am Post subject: Re: Accessing derived static member variable? |
|
|
IronGoth a écrit :
| Quote: | Here's an interesting question...
I'd like to do this:
class Person
{
protected:
virtual static std::string citizenship; //yeah, I know.
protected:
Report() { std::cout << "I am " << citizenship << std::endl; }
}
class Frenchman : public Person
{
protected:
static std::string citizenship;
}
class Englishman : public Person
{
protected:
static std::string citizenship;
}
std::string Frenchman::citizenship = std::string("French");
std::string Englishman::citizenship = std::string("English");
int main(argc, argv) // can't be arsed to look it up
{
Englishman Bertie, Rupert, Jasper;
Frenchman Jean_Guy, Jean_Paul, Jean_Marie;
Bertie.Report(); // "I am English"
Jean_Guy.Report(); // "I am French"
}
Now, I want citizenship to be STATIC that way I don't have thirty
million instances of the string "French"
I also want to have the code common to all citizenships without having
the exact same function in every single Person class.
I am very overtired but also puzzled. I was hoping there would be a way
to do this.
|
Instead of using inheritance, you can use templates, and traits (as in
numeric_limits) :
// National traits, with static members
struct France
{
static std::string nationality;
static bool eatFrog;
};
std::string France::nationality = "French";
bool France::eatFrog = true;
struct England
{
static std::string nationality;
static bool eatFrog;
};
std::string England::nationality = "English";
bool England::eatFrog = false;
// Person class, templated by a national trait class
template
struct Person
{
void Report()
{
std::cout << "I am " << NationalTraits::nationality
<< " and I";
if(!NationalTraits::eatFrog)
{
std::cout << " don't";
}
std::cout << " eat frog legs" << "n";
}
};
// A few typedef, not necessary, but more readable
typedef Person
typedef Person<England> Englishman;
int main()
{
Frenchman f;
Englishman e;
f.Report();
e.Report();
}
HTH,
--
Julien Lamy
Remove NOSPAM to reply
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Tue Jul 19, 2005 12:45 pm Post subject: Re: Accessing derived static member variable? |
|
|
In article <1121713244.751653.16770 (AT) g49g2000cwa (DOT) googlegroups.com>,
IronGoth <darkpast2000 (AT) yahoo (DOT) com> writes
| Quote: | Here's an interesting question...
I'd like to do this:
class Person
{
protected:
virtual static std::string citizenship; //yeah, I know.
|
Try:
virtual char const * const citizenship(){ return "unknown"; }
| Quote: |
protected:
Report() { std::cout << "I am " << citizenship << std::endl; }
report(std::ostream & out = std::cout) { out << "I am " |
<< citizenship() << std::endl;
| Quote: |
}
This is one of the times where using a C-style string has advantages. |
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Tue Jul 19, 2005 12:45 pm Post subject: Re: Accessing derived static member variable? |
|
|
IronGoth wrote:
| Quote: | I'd like to do this:
class Person
{
protected:
virtual static std::string citizenship; //yeah, I know.
protected:
Report() { std::cout << "I am " << citizenship << std::endl; }
}
class Frenchman : public Person
{
protected:
static std::string citizenship;
}
class Englishman : public Person
{
protected:
static std::string citizenship;
}
std::string Frenchman::citizenship = std::string("French");
std::string Englishman::citizenship = std::string("English");
Now, I want citizenship to be STATIC that way I don't have thirty
million instances of the string "French"
|
OK, that means every derived class only has one (class-static) instance of a
string with its nationality instead of each instance of the class having
such a string.
| Quote: | I also want to have the code common to all citizenships without having
the exact same function in every single Person class.
|
This means that the whole thing is implemented in the baseclass.
Instead of the string itself, you could store a reference to it in the
baseclass:
class Person {
protected:
Person( string const& nationality):
m_nationality(nationality)
{}
private:
string const& m_nationality;
};
class Frenchman: public Person
{
private:
static string const s_nationality;
public:
Frenchman():
Person(s_nationality)
{}
};
string Frenchman::s_nationality("French");
That is the least amount of duplicated code in the derived class I can think
of.
However, I'd still use a virtual function that reports the nationality of
the Person because in real life, the reference in the baseclass takes the
shape of a pointer while the virtual function will be just another virtual
function in the object's vtable. Probably slightly slower, but doesn't
require any extra size. Also, it's more obvious what it does.
Uli
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Stanimir Kabaivanov Guest
|
Posted: Tue Jul 19, 2005 3:48 pm Post subject: Re: Accessing derived static member variable? |
|
|
Hi IronGoth,
| Quote: | I'd like to do this:
class Person
{
protected:
virtual static std::string citizenship; //yeah, I know.
protected:
Report() { std::cout << "I am " << citizenship << std::endl; }
}
class Frenchman : public Person
{
protected:
static std::string citizenship;
}
class Englishman : public Person
{
protected:
static std::string citizenship;
}
std::string Frenchman::citizenship = std::string("French");
std::string Englishman::citizenship = std::string("English");
why not simply do it this way: |
class Person
{
public:
virtual void Report() =0;
}
class Frenchman : public Person
{
public:
void Report() { std::cout << "I am Frenchman"<< std::endl; }
}
I guess that's what you're trying to achive - test virtual functions
(and in this case pure virtual functions).
If you still insist on having a member that specifies citizenship, then
you can have a static enum type, or a static map containing all strings.
And then add member variable that simply points to a map entry (for
example).
But that's not the way - having member variable. Virtual functions will
be just fine, for giving different behaviour for citizens of France, UK
etc. etc.
| Quote: |
int main(argc, argv) // can't be arsed to look it up
{
Englishman Bertie, Rupert, Jasper;
Frenchman Jean_Guy, Jean_Paul, Jean_Marie;
Bertie.Report(); // "I am English"
Jean_Guy.Report(); // "I am French"
}
Now, I want citizenship to be STATIC that way I don't have thirty
million instances of the string "French"
Yes - following aforementioned instructions you won't have that many |
copies. In fact you will have only one const string for each nation in
the example I wrote.
| Quote: | I also want to have the code common to all citizenships without having
the exact same function in every single Person class.
If I get your point right, you want common code to be put in Person |
class? That's fine - virtual functions give you a chance to change only
part of the functionality. You can still have common functions in Person.
Hope this one helps,
Best regards,
Stanimir Kabaivanov
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
IronGoth Guest
|
Posted: Tue Jul 19, 2005 6:49 pm Post subject: Re: Accessing derived static member variable? |
|
|
I'd like to thank everyone for his or her reply.
Obviously templates do the trick.
However, the point I was getting at is this - I can think of many
instances in which there's something so absolutely common as to make it
a maintenance benefit etc. to keep it in the base class.
Think about a static object like a logger class - one to cover all the
logging of all objects of type Foo, and one to cover all the logging of
type Bar. However, if Foo, Bar, Baz etc. all derive from Base, and when
you look at the code for Foo, Bar, Baz, Boz, Melv, Kelv and several
others you see something like
Function() { logger->Print("Initiating Sequence");};
There's something in you that says refactor this into the base class.
However, there's no real way to do this.
You can't specify an abstract static variable - basically say something
like "lookit - in a derived class you will see a static member - use
that."
The only solution I can see is to use something like templates to
simulate reflection.
The reason I'm not keen on this as a solution
class Frenchman : public Person
{
public:
void Report() { std::cout << "I am Frenchman"<< std::endl; }
Is that if it changes from "I am Frenchman" to "Hello, I am " <<
nationality - you have to go and edit class Frenchman, Englishman,
Russian, German, Australian, AleutianIslander etc. whereas if there was
ONE copy of the function you could simply take care of it in the base.
Now this intrigues me:
class Person {
protected:
Person( string const& nationality):
m_nationality(nationality)
{}
private:
string const& m_nationality;
};
class Frenchman: public Person
{
private:
static string const s_nationality;
public:
Frenchman():
Person(s_nationality)
{}
};
I was blanking on this line: Frenchman(): Person(s_nationality)
The moment I saw that, the twin handicaps of working in Java the past
six months and no sleep for three days became apparent.... heh.
I think that sort of semantics is why C++ is superior to Java. I see NO
way to do this in Java.
Thanks again!
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
johnchx2@yahoo.com Guest
|
Posted: Wed Jul 20, 2005 9:49 am Post subject: Re: Accessing derived static member variable? |
|
|
IronGoth wrote:
| Quote: | The reason I'm not keen on this as a solution
class Frenchman : public Person
{
public:
void Report() { std::cout << "I am Frenchman"<< std::endl; }
Is that if it changes from "I am Frenchman" to "Hello, I am "
nationality - you have to go and edit class Frenchman, Englishman,
Russian, German, Australian, AleutianIslander etc. whereas if there was
ONE copy of the function you could simply take care of it in the base.
|
Isn't the obvious solution something like this:
class Person {
protected:
virtual const std::string& Nationality() = 0;
public:
void Report() {std::cout << "I am " << Nationality() << std::endl;}
};
class Frenchman: public Person {
const std::string& Nationality() {
static std::string n = "Frenchman";
return n;
}
};
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
IronGoth Guest
|
Posted: Thu Jul 21, 2005 10:20 pm Post subject: Re: Accessing derived static member variable? |
|
|
RE: class Person {
protected:
virtual const std::string& Nationality() = 0;
public:
void Report() {std::cout << "I am " << Nationality() <<
std::endl;}
};
class Frenchman: public Person {
const std::string& Nationality() {
static std::string n = "Frenchman";
return n;
}
It is, sadly. There's no way around having massive code duplication.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Fri Jul 22, 2005 1:04 pm Post subject: Re: Accessing derived static member variable? |
|
|
In article <1121973826.381664.197130 (AT) o13g2000cwo (DOT) googlegroups.com>,
IronGoth <darkpast2000 (AT) yahoo (DOT) com> writes
| Quote: | RE: class Person {
protected:
virtual const std::string& Nationality() = 0;
public:
void Report() {std::cout << "I am " << Nationality()
std::endl;}
;
class Frenchman: public Person {
const std::string& Nationality() {
static std::string n = "Frenchman";
return n;
}
What I completely fail to understand is why so many people are |
mesmerised into using std::string when they want an immutable string.
There is absolutely no need to have either a static or a std::string in
this case. If we insist on going down this path your program will call
the constructor of std::string and require storage in both the string
literal area, the static area and (unless the small string optimisation
is used) dynamic memory as well. It may even suffer further problems in
the context of multi-threading.
I know all those are small issues, but the nearest thing we have to
immutable strings in C++ are string literals so why not use them? We
then have:
char const* nationality(){
return "Frenchman";
}
which seems pretty close to:
virtual static const std::string nationality("Frenchman");
which is about what the OP seemed to want (except that it would require
at least two modifications to Standard C++). BTW my version takes less
typing:)
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
johnchx2@yahoo.com Guest
|
Posted: Sat Jul 23, 2005 1:08 am Post subject: Re: Accessing derived static member variable? |
|
|
Francis Glassborow wrote:
| Quote: | What I completely fail to understand is why so many people are
mesmerised into using std::string when they want an immutable string.
There is absolutely no need to have either a static or a std::string in
this case. If we insist on going down this path your program will call
the constructor of std::string and require storage in both the string
literal area, the static area and (unless the small string optimisation
is used) dynamic memory as well. It may even suffer further problems in
the context of multi-threading.
I know all those are small issues, but the nearest thing we have to
immutable strings in C++ are string literals so why not use them? We
then have:
char const* nationality(){
return "Frenchman";
}
|
One consideration to keep in mind: if you have a static std::string, it
will be initialized and destroyed (with corresponding heap allocation
and de-allocation) once during the entire run of the program. If you
use a function returning a C-style string, you will have to create a
temporary std::string (with attendant heap allocation and
de-allocation) every single time you want to pass the result to a
function that requires a std::string.
On reflection, I do think that a static member is probably a better
choice than a static local (slightly less thread-hostile, more
predictable time of initialization in practice).
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Sun Jul 24, 2005 6:02 pm Post subject: Re: Accessing derived static member variable? |
|
|
In article <1122047691.857856.211300 (AT) g44g2000cwa (DOT) googlegroups.com>,
"johnchx2 (AT) yahoo (DOT) com" <johnchx2 (AT) yahoo (DOT) com> writes
| Quote: | One consideration to keep in mind: if you have a static std::string, it
will be initialized and destroyed (with corresponding heap allocation
and de-allocation) once during the entire run of the program. If you
use a function returning a C-style string, you will have to create a
temporary std::string (with attendant heap allocation and
de-allocation) every single time you want to pass the result to a
function that requires a std::string.
|
However we need to look at such things in context. The context of this
one was pretty limited. And you have a problem once you have a standard
string in a MT environment because of its potential for change. Even
when you pass it around by const reference the member functions have to
deal with the possibility that the original is mutable.
a string literal is inherently immutable. Granted that it may be harder
for the compiler to verify that the pointer actual points to a literal
| Quote: |
On reflection, I do think that a static member is probably a better
choice than a static local (slightly less thread-hostil
|
Which brings you back to the original problem. Of course we are dealing
with optimisation questions here. I would have thought that a string
literal was about as thread-friendly as you can get.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Mon Jul 25, 2005 9:15 am Post subject: Re: Accessing derived static member variable? |
|
|
Francis Glassborow wrote:
| Quote: | What I completely fail to understand is why so many people are
mesmerised into using std::string when they want an immutable string.
|
I'd guess it's consistency and the fact that raw pointers are dangerous and
ugly. Yes, there's some irony in my words. ;)
| Quote: | There is absolutely no need to have either a static or a std::string in
this case. If we insist on going down this path your program will call
the constructor of std::string and require storage in both the string
literal area, the static area and (unless the small string optimisation
is used) dynamic memory as well. It may even suffer further problems in
the context of multi-threading.
|
I have the latent idea in the back of my mind that it might be useful to
have a string class with a changing type. What I mean is that it might be
useful to extend the two current types 'static internal buffer' and
'dynamic external buffer' with a few more like 'external, immutable string
literal' or 'chained list of several dynamic buffers'.
The first would require an extension to the standard (or the compiler) so
that you can tell the constructor that the backing storage is immutable.
The 'chained list of several dynamic buffers' would mean that e.g.
concatenation would create a new string that stores pointers to both
sources' storage (after incrementing their refcounter...). Calling c_str()
would mean first replacing the pieces by a contiguous memory array before
returning a pointer to it.
This is just a raw idea, I haven't created a prototype yet nor did I think
it through to the end, but does it sound like a bad idea (apart from the
increased complexity for the implementor) from the beginning?
Uli
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tokyo Tomy Guest
|
Posted: Mon Jul 25, 2005 9:16 am Post subject: Re: Accessing derived static member variable? |
|
|
"IronGoth" <darkpast2000 (AT) yahoo (DOT) com> wrote
| Quote: | The only solution I can see is to use something like templates to
simulate reflection.
|
Though I do not think I understand the OP's intention, from the fact
that the OP want to simulate reflection, I guess that the following
code is near his intention. Anyway, you have to write county names and
natinalities at least.
[code]
#include <iostream>
#include <string>
enum { French, English, Germany, Japan };
std::string nationality[] = { "Frenchman", "Englishman", "German",
"Japanese"};
template <int N>
class Person {
public:
static void Report() { std::cout << "I am " << nationality[N] <<
std::endl;}
};
int main() {
Person
James.Report();
Person<Japan> Tomio;
Tomio.Report();
return 0;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|