Changing virtual function output without using any data member

Instead of this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
struct Object {
    int size;  // Want to avoid this because size is (almost always) constant 
    Object (int s): size(s) {}  // for every Object subtype.
};

struct Block: Object {  // Suppose there are millions of Block instances in the program
    Block(): Object(5) {}  // Don't want this method, which forces Object 
    int getSize() const {return size;}  // to have the int size data member.
};

void changeSize (Object* object, int newSize) {  // This is called once in a blue moon only (hence is not a member function).
    object->size = newSize;  
}

int main() {
    Block* block = new Block;
    changeSize (block, 6);
    std::cout << block->getSize() << std::endl;
} 


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

struct Object {
    virtual int getSize() const = 0;
};

struct Block: Object {
    int getSize() const {return 5;}  // always 5, except once in a blue moon it may change
};

void changeSize (Object* object, int newSize) {
    // What to put here ???
}

int main() {
    Block* block = new Block;
    changeSize (block, 6);
    std::cout << block->getSize() << std::endl;  // Want to show 6 instead of 5.
}


The Decorator Pattern works (getSize() can then return 6) but it is a poor choice for my program because it will cause more problems (due to many containers holding its old address, among other things). Any other ideas? Anyway to achieve this without any change of address, and without creating new storage somewhere, either inside the class or outside the class (too much responsibility to follow that stored value for the rest of the program just for this rare change, and creating a data member uses up too much memory for the many, many Block instances)?
Last edited on
I think you are trying to do the impossible. If you want objects to have different properties you will have to store that information somewhere and that will require some memory.

Note that if you have virtual functions your class will have to store some additional information (usually the size of a pointer) to be able to lookup the correct type and functions to call. On most (all?) implementations it doesn't matter if you have 1 or more virtual functions, the memory overhead for each object would be the same, but if this is the only virtual function you have you could just as well store the size as a member variable. That might even take up less memory and be more efficient.
@Peter87, so you are saying that giving the int size data member to Block, where there are millions of Block instances in the program storing value 5 and one storing value 6, will NOT create more memory storage than this code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <typeinfo>

struct Object {
    // no int size data member
    virtual int getSize() const = 0;
};

struct Block: Object {
    virtual ~Block() = default;
    int getSize() const override {return 5;}  // always 5, except once in a blue moon it may change
};

struct BlockDecorator: Block {  // simplified Decorator Pattern, avoiding templates and stuff
	Block* block;
	BlockDecorator (Block* oldBlock): block (oldBlock) {}
	int getSize() const override {return 6;}
};

void changeSize (Block*& block, int newSize) {
    block = new BlockDecorator (block);
}

int main() {
    Block* block = new Block;
    std::cout << block->getSize() << std::endl;  // 5
    changeSize (block, 6);
    std::cout << block->getSize() << std::endl;  // 6
} 
//  This works, and block is still of type Block, but alas, the change in block's address
//  causes problems for the rest of the program (omittied here of course). 
Last edited on
check sizeof(Block) with and without virtual functions
Ok, sizeof(Block) is the same in both versions. So does that mean that the free store used up by millions of Block instances with data member int size, compared to millions of Block instances with no data member at all, will be the same?
Last edited on
@Peter87, so you are saying that giving the int size data member to Block, where there are millions of Block instances in the program storing value 5 and one storing value 6, will NOT create more memory storage than this code?


The code you supplied will actually use more memory (and is more error prone - for instance, in addition to actually taking more memory, it leaks some of it.)
Topic archived. No new replies allowed.