How to access a derived pointer member from base?



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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <string>
#include <memory>
#include <stdio.h>
#include <string.h>


class RGB {
    public:
 
 int num=0;
 uint32_t *color=NULL;
 RGB(int N, uint32_t *icolor):num(N),color(icolor){ fprintf(stdout, "Base called\n");};
    
};    

class RGB24: public RGB {
    public:
 uint32_t *colord=(uint32_t*)malloc(12);
 
   RGB24():RGB(3,colord){  //base *color now points to memory pointed to by colord
       //color=(uint32_t*)malloc(3);
       
       *colord=5;
       *(colord+1)=1;
       *(colord+2)=3;
       
       };
       
    ~RGB24(){
      free(color);  
    };    
       
       
};    
  

int main() {
    
RGB *rgb;
RGB24 *rgb24=new RGB24;
fprintf(stdout,"%d\n", *(rgb24->colord));
fprintf(stdout,"%d\n", *(rgb24->colord+1));
fprintf(stdout,"%d\n", *(rgb24->colord+2));
rgb=rgb24;

//fprintf(stdout,"%d\n", *rgb->color);    //dereference base color should output 5 but segfaults instead
//fprintf(stdout,"%d\n", *rgb->color+1);
//fprintf(stdout,"%d\n", *rgb->color+2);

delete rgb24;  
}


Thanks,
Chris
Last edited on
if you add another print to
{ fprintf(stdout, "Base called\n");};
for icolor, you will see that it is zero / null
for some reason its not being passed correctly as far as I can tell, but I don't yet see why.

why in the world are you mixing c++ and c like this? mixing malloc and new causes trouble (as does mixing delete and free; if you try to delete something made with malloc or free something from new, it may misbehave), and there is no good reason to use printf instead of cout here. The printfs don't hurt anything but the pointer mixing will.

once you fix the null pointer, it may work as is, or it may need () as in
*(rgb->color)

or rgb->color[0]

its getting late and im not sure if you need to mess with the access line or not. Its crashing bc null pointer, not the way you tapped it.
Last edited on
I don't understand all your purpose, but this example can be helpful.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>

class RGB {
public:
    int num;
    uint32_t *color;
    RGB(int _num, uint32_t *_color):num(_num),color(_color){ 
        std::cout<<"Base called"<<std::endl;
    }
    ~RGB(){ 
        std::cout<<"Base destructor"<<std::endl;
        delete color;
    }
};    


class RGB24: public RGB {
public:
    RGB24():RGB(0,0){
        std::cout<<"Derived called"<<std::endl;
        num = 3;
        color = new uint32_t[num];
        color[0]=5;
        color[1]=1;
        color[2]=3;
    }
    ~RGB24(){
        std::cout<<"Derived destructor"<<std::endl;
    }
};    
  

int main() {
    
    RGB *rgb;
    RGB24 *rgb24 = new RGB24;

    std::cout << rgb24->color[0]<<std::endl;
    std::cout << rgb24->color[1]<<std::endl;
    std::cout << rgb24->color[2]<<std::endl;
    
    rgb = rgb24;
    std::cout << rgb->color[0]<<std::endl;
    std::cout << rgb->color[1]<<std::endl;
    std::cout << rgb->color[2]<<std::endl;


    std::cout<<"New assignment"<<std::endl;
    rgb24->color[0] = 2;
    rgb24->color[1] = 2;
    rgb24->color[2] = 2;
    
    std::cout << rgb24->color[0]<<std::endl;
    std::cout << rgb24->color[1]<<std::endl;
    std::cout << rgb24->color[2]<<std::endl;
    
    std::cout << rgb->color[0]<<std::endl;
    std::cout << rgb->color[1]<<std::endl;
    std::cout << rgb->color[2]<<std::endl;
    
    delete rgb24;  
}


$g++ -o main *.cpp
$main
Base called
Derived called
5
1
3
5
1
3
New assignment
2
2
2
2
2
2
Derived destructor
Base destructor
> for icolor, you will see that it is zero / null
> for some reason its not being passed correctly as far as I can tell, but I don't yet see why.
construction order
first the base is constructed, then the members of the derived

@homy18, you are mixing new[] with delete (it should be delete[])
also, ¿why is `base' deleting?
How to access a derived pointer member from base?

When you write a class, you cannot know whether anyone derives from it. Ever.
Therefore, for base there is no "derived".

(Exception: abstract class is unusable without inheritance, but it still knows nothing about the derived.)

Base can have virtual member functions. They allow derived objects to differentiate in behaviour from the base. The base makes that possible.


What is the overall design goal?
Is RGB24 just one example of many classes that will all derive from RGB?

You probably have an XY Problem. You try to achieve Y. You have written X, thinking it is the solution. It does not quite work. You ask help with X. However, X is not the way to solve Y. Please, explain the Y to us first.
Last edited on


I am trying to condense this piece of code to either a template solution or polymorphic solution. Basically, I need to step through a uint8_t buffer either by single byte, three byte at a time or 4 bytes at a time depending on the type of the buffer wether RGB8, RGB24, or RGBA. I need a common pointer that can be casted into the proper buffer type.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Example program
#include <iostream>
#include <memory>
#include <stdio.h>
#include <string.h>


struct RGB8 {
   uint8_t G;	
};	

struct RGB24 {
   uint8_t R;
   uint8_t G;
   uint8_t B;	
};	

struct RGBA {
   uint8_t R;
   uint8_t G;
   uint8_t B;
   uint8_t A;		
};	



int main() {
	

  
  uint8_t * buffer=(uint8_t*)malloc(100);
  uint8_t values[100]={0x63,0x61,0x74,0x73,0x64,0x6f,0x67,0x73}; //catsdogs
  memcpy(buffer, &values, 100);
  
  fprintf(stderr,"Buffer values\n");
  for (uint32_t i = 0; i < 8; ++i) {
                    fprintf(stderr, "\\%02x", (unsigned char)*(buffer+i));
  }   
  fprintf(stderr,"\n"); 
  
  fprintf(stderr,"Buffer values stepped one byte at a time\n");
  RGB8 *rgb8=(RGB8*)buffer;
  for (uint32_t i = 0; i < 8; ++i) {
                    fprintf(stderr, "\\%02x", (unsigned char)(rgb8+i)->G);
                    fprintf(stderr," ");
  }   
  fprintf(stderr,"\n"); 
  
  fprintf(stderr,"Buffer values stepped three bytes at a time\n");
  RGB24 *rgb24=(RGB24*)buffer;
  for (uint32_t i = 0; i < 2; ++i) {
                    fprintf(stderr, "\\%02x", (unsigned char)(rgb24+i)->R);
                    fprintf(stderr, "\\%02x", (unsigned char)(rgb24+i)->G);
                    fprintf(stderr, "\\%02x", (unsigned char)(rgb24+i)->B);
                    fprintf(stderr," ");
  }   
  fprintf(stderr,"\n"); 
  
  fprintf(stderr,"Buffer values stepped four bytes at a time\n");
  RGBA *rgba=(RGBA*)buffer;
  for (uint32_t i = 0; i < 2; ++i) {
                    fprintf(stderr, "\\%02x", (unsigned char)(rgba+i)->R);
                    fprintf(stderr, "\\%02x", (unsigned char)(rgba+i)->G);
                    fprintf(stderr, "\\%02x", (unsigned char)(rgba+i)->B);
                    fprintf(stderr, "\\%02x", (unsigned char)(rgba+i)->A);
                    fprintf(stderr," ");
                    
  }   
  fprintf(stderr,"\n"); 
  
  
  
  free(buffer);
  
}


The question however was about using a base pointer to access derived members. ( In my pursuit to find a solution) I have read that this is not possible as base pointer will only have access to base members when it is assigned a derived object's address. Just wondering if the use of pointers will make this type of access possible. I figured if the base object is handed a derived object's malloc'd pointer address, then it could somehow perform operations on the data that pointer is pointing to as if the base itself did the malloc.

construction order
first the base is constructed, then the members of the derived


I guess it is impossible then if you use the base constructor to pass the value. The pointer member of derived will be constructed after the base portion is created so we cannot pass the value over from derived to base. However, homy18's solution works. Isn't he assigning an address from derived to base? He is not using the base constructor. Still, the base pointer now points to a pointer that was created in derived object. Here is the original code reworked, no constructor arguments this time.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <string>
#include <memory>
#include <stdio.h>
#include <string.h>


class RGB {
    public:
 
 int num=0;
 uint32_t *color=NULL;
 RGB(){ fprintf(stdout, "Base called\n");};
    
};    

class RGB24: public RGB {
    public:
 
 
   RGB24():RGB(){  //base *color now points to memory pointed to by colord
       //color=(uint32_t*)malloc(3);
       color=(uint32_t*)malloc(12);
       *color=5;
       *(color+1)=1;
       *(color+2)=3;
       
       };
       
    ~RGB24(){
      free(color);  
    };    
       
       
};    
  

int main() {
    
RGB *rgb;
RGB24 *rgb24=new RGB24;
fprintf(stdout,"%d\n", *(rgb24->color));
fprintf(stdout,"%d\n", *(rgb24->color+1));
fprintf(stdout,"%d\n", *(rgb24->color+2));
rgb=rgb24;

fprintf(stdout,"%d\n", *rgb->color);    //dereference base color should output 5 but segfaults instead
fprintf(stdout,"%d\n", *(rgb->color+1));
fprintf(stdout,"%d\n", *(rgb->color+2));

delete rgb24;  
}





Here is a template solution to the original code problem I am trying to solve, but again, no common base pointer. I think I am missing something really obvious.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Example program
#include <iostream>
#include <string>
#include <memory>
#include <stdio.h>
#include <string.h>

template <int N>
class RGB {
    
  public:
  uint8_t color[N];

};
  
 
int main()
{

uint8_t *buffer=(uint8_t*)malloc(100);
uint8_t values[100]={0x63,0x61,0x74,0x73,0x64,0x6f,0x67,0x73}; //catsdogs
memcpy(buffer, &values, 100);

int colour=4;

if (colour==3) {

  RGB<3> *rgb=(RGB<3>*) buffer;
  for (int i=0; i< colour ; i++)
     std::cout << rgb->color[i] << std::endl; //cat
} else {

  RGB<4> *rgba=(RGB<4>*) buffer;
  for (int i=0; i< colour ; i++)
     std::cout << rgba->color[i] << std::endl; //cats
   
  for (int i=0; i< colour ; i++)
     std::cout << (rgba+1)->color[i] << std::endl; //dogs   
}



free(buffer);
  
}




Thanks,
Chris
Last edited on
Here is what I have come up with so far. There has to be a more elegant solution. Why is pointer arithmetic not working on the common procedure though? Its incrementing 1 byte instead of the size of the casted to class.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Example program
#include <iostream>
#include <memory>
#include <stdio.h>
#include <string.h>

class RGB {
	public:
    uint8_t R;

};

class RGB24 : public RGB {
	public:
	uint8_t G;
	uint8_t B;
	
};

class RGBA : public RGB24 {
	public:
	uint8_t A;
};

    

int main() {
	
  RGB *rgb=NULL; //common pointer

  
  uint8_t * buffer=(uint8_t*)malloc(100);
  uint8_t values[100]={0x63,0x61,0x74,0x73,0x64,0x6f,0x67,0x73}; //catsdogs
  memcpy(buffer, &values, 100);
  for (uint32_t i = 0; i < 8; ++i) {
                    fprintf(stdout, "\\%02x", (unsigned char)*(buffer+i));
  }   
  fprintf(stdout,"\n"); 
  
  std::string name;
  std::cout << "What is the colour? ";
  getline (std::cin, name);
  
  uint32_t colour=std::stoi(name);
  
  switch (colour) {
	  case 1:
        rgb=(RGB*)buffer; //no effect on pointer arithmetic
        fprintf(stdout,"RGB\n");
        break;
      case 3:
        rgb=(RGB24*)buffer; //no effect on pointer arithmetic
        fprintf(stdout,"RGB24\n");
        break;
      case 4:
        rgb=(RGBA*)buffer; //no effect on pointer arithmetic
        fprintf(stdout,"RGBA\n");
        break;
   }     
  
  
  //one procedure to deal with all cases given a common pointer
  for (uint32_t k=0; k< 8/colour ; k++ ) {
     for (uint32_t i = 0; i < colour; ++i) {
                    fprintf(stdout, "\\%02x", (unsigned char)((rgb+i)->R));
      }  
     rgb+=colour;  //pointer rgb increments one byte with all the cases
     fprintf(stdout," ");
  }
  fprintf(stderr,"\n");
  
  
  free(buffer);
  
}
Last edited on
I need to step through a uint8_t buffer either by single byte, three byte at a time or 4 bytes at a time depending on the type of the buffer wether RGB8, RGB24, or RGBA.

You want to iterate over an array of values.

I presume this is not a solution to that:
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
32
33
34
35
36
37
#include <iostream>

struct Foo {
    size_t stride;
    uint8_t* pos;
    Foo( size_t s, uint8_t* p )
    : stride(s), pos(p) {}
    Foo & operator++ ()
    { pos += stride; return *this; }
};

std::ostream& operator<< ( std::ostream& out, const Foo & f ) {
  for ( size_t x=0; x < f.stride; ++x ) out << ' ' << f.pos[x];
  return out;
}

int main() {
  constexpr size_t VS {8};
  uint8_t values[VS] {0x63,0x61,0x74,0x73,0x64,0x6f,0x67,0x73};
  for ( auto x : values ) std::cout << ' ' << x;
  std::cout << '\n';

  std::cout << "1:\n";
  for ( Foo x( 1, values ); x.pos + x.stride <= values+VS; ++x ) {
    std::cout << x << '\n';
  }

  std::cout << "3:\n";
  for ( Foo x( 3, values ); x.pos + x.stride <= values+VS; ++x ) {
    std::cout << x << '\n';
  }

  std::cout << "4:\n";
  for ( Foo x( 4, values ); x.pos + x.stride <= values+VS; ++x ) {
    std::cout << x << '\n';
  }
}
See http://www.cplusplus.com/doc/tutorial/polymorphism/ for polymorphism.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//RGB experiment
#include<iostream>
#include<cstdint>

class RGB{
protected:
	uint8_t *rgb;
	int num;
public:
	RGB(uint8_t *data, int n){
		num = n;
		rgb = new uint8_t[num];
		for(int i=0; i<num; i++)
			this->rgb[i] = data[i];
	}
	~RGB(){
		delete [] rgb;
	}
	void set(const uint8_t &d, const int &idx){
		this->rgb[idx]=d;
	}
};

class RGB8:public RGB{
public:
	RGB8(uint8_t *data, int n):RGB(data,n){}
	~RGB8(){}
	const uint8_t & G(const int &idx) const {
		if(idx > num) throw ;
		return this->rgb[idx];
	}
};

class RGB24:public RGB8{
public:
	RGB24(uint8_t *data, int n):RGB8(data,n){}
	~RGB24(){}
	const uint8_t & R(const int &idx) const {
		if(idx > num/3) throw ;
		return this->rgb[idx*3];
	}	
	const uint8_t & G(const int &idx) const {
		if(idx > num/3) throw ;
		return this->rgb[idx*3+1];
	}
	const uint8_t & B(const int &idx) const {
		if(idx > num/3) throw ;
		return this->rgb[idx*3+2];
	}
};

class RGBA:public RGB24{
public:
	RGBA(uint8_t *data, int n):RGB24(data,n){}
	~RGBA(){}
	const uint8_t & R(const int &idx) const {
		if(idx > num/4) throw ;
		return this->rgb[idx*4];
	}	
	const uint8_t & G(const int &idx) const {
		if(idx > num/4) throw ;
		return this->rgb[idx*4+1];
	}
	const uint8_t & B(const int &idx) const {
		if(idx > num/4) throw ;
		return this->rgb[idx*4+2];
	}
	const uint8_t & A(const int &idx) const {
		if(idx > num/4) throw ;
		return this->rgb[idx*4+3];
	}
};


int main(){

	uint8_t values[100]={0x63,0x61,0x74,0x73,0x64,0x6f,0x67,0x73};
	RGBA rgba(values, 100);
	
	RGB *rgb = &rgba;
	rgb->set('f',8);
	rgb->set('i',9);
	rgb->set('s',10);
	rgb->set('h',11);
	
	RGB8 *rgb8 = &rgba;
	std::cout<<"RGB8:\n";
	for(int i = 0; i<12; i++)
		std::cout<<rgb8->G(i)<<"\n";
		
	RGB24 *rgb24 = &rgba;
	std::cout<<"\nRGB24:\n";
	for(int i = 0; i<3; i++)
		std::cout<<rgb24->R(i)
				 <<rgb24->G(i)
				 <<rgb24->B(i)
				 <<"\n";
		
	RGBA *rgba2 = &rgba;
	std::cout<<"\nRGBA:\n";
	for(int i = 0; i<3; i++)
		std::cout<<rgba2->R(i)
				 <<rgba2->G(i)
				 <<rgba2->B(i)
				 <<rgba2->A(i)
				 <<"\n";
	
	return 0;
}
Last edited on
> However, homy18's solution works. Isn't he assigning an address from derived to base?
he's working on Base::color directly, and can do that because everything is public.
there's also some error-prone memory management (derive is responsible of creation, but base of deletion)
edit: ah, you change it


> Why is pointer arithmetic not working on the common procedure though?
https://wiki.sei.cmu.edu/confluence/display/cplusplus/CTR56-CPP.+Do+not+use+pointer+arithmetic+on+polymorphic+objects
Pointer arithmetic does not account for polymorphic object sizes



I like keskiverto's solution
it could be better if you manage to encapsulate the x.pos + x.stride <= values+VS condition
Last edited on
Thanks Guys,
These are really good answers. I might be trying to solve this problem the wrong way. My initial idea was to come up with a base class and derived classes for each type of rgb buffer. I am trying to write an RGB buffer writing function that modifies pixel colors in the buffer. My plan was to come up with a function that takes a base pointer, but the call to the function will actually send a derived pointer. Then in the function use pointer arithmetic to arrive at the proper address. However pointer arithmetic cannot be performed on polymorphic objects as per the link from ne555.

My other concern is the speed of the writing operation. As much as possible I need to avoid memcpy or assignment and need to operate on the buffer directly with the least amount of code. This is on a raspberry pi3.

Here is my implementation so far, just handling one type of buffer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

//in the header file
struct RGB24 {
	   uint8_t R=0;
	   uint8_t G=0;
	   uint8_t B=0;	
	};	
	
	RGB24 *RGB=NULL;

//in the cpp file

if (colours == 3 )  
         RGB=(RGB24*)directbuffer; 

// Intend the code below to become a function that takes a pointer and an index and modify the pixel at that index. 
//The pointer must be such that arithmetic on it arrives at the proper address so +1 should properly step 1 byte, 3 bytes, 4 bytes. 

if ((Block+index)->rgbindex >=0) {     
                                     (RGB+((Block+index)->rgbindex))->R=255; //write a white pixel
                                     (RGB+((Block+index)->rgbindex))->G=255;
                                     (RGB+((Block+index)->rgbindex))->B=255;
							       }


The index is the macroblock index and rgbindex is the top left pixel on the macroblock. There are macro Blocks that don't have pixels in the RGB buffer. I pre computed the indexes of the top left pixel of each 16x16 macroblock and assigned that to each consecutive Block object in a Block array. I assigned a -1 to rgbindex of the Blocks that don't have pixels in the RGB buffer.

I could come up with a global pointer for each RGB type and based on the value of colour (1 for RGB8, 3 for RGB24 and 4 for RGBA) cast directbuffer to the proper pointer type, but that means I have to duplicate the pixel writing code three times for each case since there are three types of unrelated RGB pointers to deal with.

Or I can just stick to uint8_t* which is the type of directbuffer and modify the pixel at the index by writing successive colour bytes. So at directbuffer+((Block+index)->rgbindex) I need to write three consecutive bytes for colour=3.

1
2
3
4
5
if ((Block+index)->rgbindex >=0) {  
		  for (int m=0; m < colour ; m++) {   
                                       *(uint8_t*)(directbuffer+(((Block+index)->rgbindex)+m))=255; //this should write a white pixel but it doesn't.  
		  }
} 


Is there a better solution?

Also I have run into a snag with the last pixel writing codeblock above. It doesn't seem to be working. From what I can see, it is equivalent to the first codeblock.

Thanks,
Chris
Last edited on
Topic archived. No new replies allowed.