Clarifying some points

Hi, I started learning C++ a couple of days ago as I hear it is a superior language to C for general purpose programming, and have a few questions.

Question 1:

This question regards using forward declared constant values as sizes for fixed length arrays.

I would like to be able to compile code like this:

Header:
1
2
3
4
5
6
class Example
{
    private:
        static unsigned const ARRAY_SIZE;
        unsigned myArray[ARRAY_SIZE];
};


Source:
1
2
3
4
#include "Header.hpp"

unsigned const
    ARRAY_SIZE = 10;


However, this does not compile as the size of class Example must be resolvable from the source in the header file. So I have considered a "solution" along the lines of having a file of constants as follows:

Constants:
1
2
3
4
namespace Constants
{
    unsigned const ARRAY_SIZE = 10;
}


and then adding it in my makefile as a dependency which, when altered, causes total recompilation. The only advantage of this over the typical "make clean" followed by "make" to address the change of definitions which exist through necessity in a header file is that the rebuild is then automated by the make. However, it is obviously an inefficient compilation process. Is there a way to resolve this problem which I have missed?


Question 2:

This question regards polymorphism and memory allocation.

I have code like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Base
{
    protected:
        unsigned data;
    public:
        virtual void editData() = 0;
};

class A: public Base
{
    public:
        void editData() { data = 1; };
};

class B: public Base
{
    public:
        void editData() { data = 2; };
};


Now, in order to actually utilise this polymorphism, I need code like this:

Base *a[2] = { new A(), new B() };
a[0]->editData();
a[1]->editData();

and then at some point I require:

delete [] a;

Since inherited classes A and B add no additional size to the base class Base I would like to use a fixed length array of instances of A or B. This would avoid unnecessary memory allocation and additional pointer resolution. Have I overlooked some code structures to allow for inherited classes which do not increase the size of the base class?


Question 3:

This question regards forward declarations of enumerations.

I often define a lot of constants in my code for the obvious purpose of increasing readability. However, I cannot seem to get forward declarations of enumerations to work.

I am aware of the issue of data size resolution with forward declaration of enumerations, and am lead to believe that c++0x allows this to be resolved by giving the underlying type of the enumeration. However, I cannot find example code or get anything to compile. What I am currently trying is something like:

Header:
1
2
3
4
5
class Example
{
    private:
        enum E: unsigned;
};


Source:
1
2
3
4
5
enum Example::E
{
    Val1 = 10,
    Val2 = 20
};


Besides inability to compile forward declared enumerations, I don't know what the advantage of enumerations over constants is. For example, why would enumerations be better than say:

Header:
1
2
3
4
5
6
7
class Example
{
    private:
        static unsigned const
            Val1,
            Val2
};


Source:
1
2
3
unsigned const
    Example::Val1 = 10,
    Example::Val2 = 20;


Which works just fine and only has the somewhat superficial difference that enumerations define a type name associated with the enumeration, but if that is important it could be addressed with:

Header:
1
2
3
4
5
6
7
8
class Example
{
    private:
        typedef unsigned E;
        static E const
            Val1,
            Val2
};


Source:
1
2
3
Example::E const
    Example::Val1 = 10,
    Example::Val2 = 20;


And I am lead to believe that typedefs follow the same scoping rules as enumerations.


Question 4:

To read/write an instance of a class, is the following acceptable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <fstream>

class Example
{
    private:
        char data[DATA_LEN];
    public:
        char moreData[MORE_DATA_LEN];
        void read(std::istream*);
        void write(std::ostream*);
};

Example::read(std::istream *is)
{
    is->read((char*)this, sizeof(Example));
}

Example::write(std::ostream *os)
{
    os->write((char*)this, sizeof(Example));
}


Assuming the class:
- Contains no non-static pointers.
- Contains no virtual/override functions.

i.e. my question is can one assume that the data members of a class are stored contiuously and in the order in which they are declared? In particular, will multiple compilers consistently give the same file format as a result of this code?

The motivation behind this question is that it is clearly inefficient to read each field from an input stream with individual and unnecessary function calls to the input or output stream.


Question 5:

How are virtual functions implemented? My assumption was that a virtual function would be compiled as both the function and a data member in the class which is a pointer to the function, then overriding the function in an inherited class would create a new function and would override the pointer to the new function. Hence I made this test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

using namespace std;

class A
{
    public:
        virtual void Hello() { cout << "A" << endl; };
};

class B: public A
{
    public:
        void Hello() { cout << "B" << endl; };
};

int main(int argc, char *argv[])
{
    A a = B();
    a.Hello();
    return 0;
}


This code, sadly, prints "A". Thus, I don't know how the compiler implements virtual functions. Interestingly, by adding a virtual function the sizeof A goes from 1 (what I believe is a dummy byte to disambiguate multiple instances of a class which has no data members by forcing instances to occupy different areas in memory), up to 4, the size of a pointer. However, when I try to interpret this memory and interpret it as a pointer to a function all I get is a crash - e.g.:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

using namespace std;

class A
{
    public:
        virtual void Hello() { cout << "A" << endl; };
};

int main(int argc, char *argv[])
{
    A a = A();
    unsigned *p = (unsigned*)&a;
    void (*f)(A*) = (void (*)(A*)) (*p);
    f(&a);
    return 0;
}


As C++ forbids taking the address of a member function, I am left in the dark as to the implementation of virtual functions.

Thanks in advance for your help!
NB/ NO CODE IN THIS POST HAS BEEN TESTED, THERE MAY BE TRIVIAL SYNTAX ERRORS.
Question 1:
You need to define a static const variable during it's declaration (in header file). You don't want that? No point of using a separate file.

Question 2:
Polymorphism requires the existence of dynamically allocated instances. Otherwise won't work. You are going to crate the array using some type Base, A or B. That's the type all elements would be if not dynamically allocated.

Maybe your compiler would complain if you assign element values maybe not. This is not important (it depends if your assigned object can be implicitly casted to the required one- the one you define your array holds). The important is that you won't be able to treat each element differently.

Question 3:
I am not sure I can answer this question thoroughly but enums are at least preferered over const in case of global defined const since the latter ones does not have a fixed order to be read if are contained in multiple files.

Question 4:
data[DATA_LEN]; is expected to contain elements stored side by side. This same applies to the second array. But I am not sure that first and second array are continuous to each other. I am not sure about the ineffiecnt part also.

Question 5:
As I said before virtual means that function is known only during runtime. This requires dynamically allocated objects involved. Virtual functions are implemented by a compiler using a table (I think it's called vtable) where the different versions of the functions have a pointer to them. Then during runtime it's decided what function to use.

A a is always a A object.

Question 1:
You need to define a static const variable during it's declaration (in header file). You don't want that? No point of using a separate file.


I have working code of the following format:

Header:
1
2
3
4
5
6
7
class
{
    public:
        static unsigned const
            VAL_1,
            VAL_2;
};


Source:
1
2
3
4
5
#include "Header.hpp"

unsigned const
    Example::VAL_1 = 10,
    Example::VAL_2 = 20;


The point being that when I compile the values of these constants are stored in the object file, and references to them are only resolved during linking. Hence when I change these values in the source file and it is recompiled to the object file when the object files are relinked to create the final executable the other object files do not require recompiliation, hence I have an efficient compilation process. If, however, I change the value of the constant in the header file all source files using that header file are effectively changed and require recompilation.


Question 3:
I am not sure I can answer this question thoroughly but enums are at least preferered over const in case of global defined const since the latter ones does not have a fixed order to be read if are contained in multiple files.


I'm sorry, I don't know what you mean by "a fixed order to be read if are contained in multiple files". Could you elaborate this point further, please?


Question 4:
data[DATA_LEN]; is expected to contain elements stored side by side. This same applies to the second array. But I am not sure that first and second array are continuous to each other. I am not sure about the ineffiecnt part also.


If I make repeated calls to the input or output streams for each variable I want to read or write then each call would entail an unnecessary function call when only one would do. That is, assuming I can treat my class as being made up of contiguous data.


I take it from your answers to questions 2 and 5 that polymorphism is usually going to be inefficient for what I want - much as I suspected.
sorry to intrude, but I thought a self made header file was .h not .hpp what is the difference?
sorry to intrude, but I thought a self made header file was .h not .hpp what is the difference?


Ultimately, nothing. They're both plain text files, and if all you do with your header file is #include them, the compiler never even sees the existence of the header file. The choice of .h or .hpp is convention only; some people use hpp to indicate a header file written in C++ rather than in C.
Last edited on
ok thanks
Topic archived. No new replies allowed.