By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,498 Members | 1,564 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,498 IT Pros & Developers. It's quick & easy.

Problem with abstract base class

P: n/a
Suppose I have an abstract base class that looks like this:

template <typename T>
class base {
public: // Typedefs
typedef double value_type;
typedef std::size_t size_type;
public:
// Assignment operators.
virtual base<T>& operator=(const base<T>& rhs) = 0;
virtual base<T>& operator=(const value_type& rhs) = 0;
// Indexing operators.
virtual value_type& operator()(size_type i, size_type j) = 0;
virtual const value_type& operator()(size_type i, size_type j) const
= 0;
// Size functions.
virtual size_type size() const = 0;
virtual size_type rows() const = 0;
virtual size_type columns() const = 0;
// Elementwise mathematical operators
virtual base<T>& operator+=(const base<T>& rhs) = 0;
virtual base<T>& operator-=(const base<T>& rhs) = 0;
virtual base<T>& operator*=(const base<T>& rhs) = 0;
virtual base<T>& operator/=(const base<T>& rhs) = 0;
virtual base<T>& operator+=(const value_type& rhs) = 0;
virtual base<T>& operator-=(const value_type& rhs) = 0;
virtual base<T>& operator*=(const value_type& rhs) = 0;
virtual base<T>& operator/=(const value_type& rhs) = 0;
};

and a derived class:

template <typename T>
class image : public base<T> {
protected: // Data members
value_type *m_data;
size_type m_rows, m_columns;
public:
// Constructors and destructor.
image();
image(size_type m, size_type n);
image(size_type m, size_type n, const value_type& init);
image(const image<T>& rhs);
~image();
// Assignment operators.
image<T>& operator=(const base<T>& rhs);
image<T>& operator=(const value_type& rhs);
// Indexing operators.
value_type& operator()(size_type i, size_type j);
const value_type& operator()(size_type i, size_type j) const;
// Size functions.
size_type size() const;
size_type rows() const;
size_type columns() const;
// Elementwise mathematical operators
image<T>& operator+=(const base<T>& rhs);
image<T>& operator-=(const base<T>& rhs);
image<T>& operator*=(const base<T>& rhs);
image<T>& operator/=(const base<T>& rhs);
image<T>& operator+=(const value_type& rhs);
image<T>& operator-=(const value_type& rhs);
image<T>& operator*=(const value_type& rhs);
image<T>& operator/=(const value_type& rhs);
};

When i want to use the assignment operator in my code, even a simple
program won't compile:

int main(void)
{
image<double> im1(512,512), im2(512,512);
im1 = im2;
return 0;
}

With VC7.1 I receive this error message:

main.obj : error LNK2019: unresolved external symbol "public: virtual
class image::base<double> & __thiscall
image::base<double>::operator=(class image::base<double> const &)"
(??4?$base@N@image@@UAEAAV01@ABV01@@Z) referenced in function "public:
class image::image<double> & __thiscall
image::image<double>::operator=(class image::image<double> const &)"
(??4?$image@N@image@@QAEAAV01@ABV01@@Z)
Jul 23 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Jef Driesen wrote:
Suppose I have an abstract base class that looks like this:

template <typename T>
class base {
public:
// Assignment operators.
virtual base<T>& operator=(const base<T>& rhs) = 0; [...] };

and a derived class:

template <typename T>
class image : public base<T> {
public:
// Assignment operators.
image<T>& operator=(const base<T>& rhs); [...] };

When i want to use the assignment operator in my code, even a simple
program won't compile:
It won't *link*. It compiles apparently fine.

int main(void)
{
image<double> im1(512,512), im2(512,512);
im1 = im2;
return 0;
}

With VC7.1 I receive this error message:

main.obj : error LNK2019: unresolved external symbol "public: virtual
class image::base<double> & __thiscall
image::base<double>::operator=(class image::base<double> const &)"
(??4?$base@N@image@@UAEAAV01@ABV01@@Z) referenced in function "public:
class image::image<double> & __thiscall
image::image<double>::operator=(class image::image<double> const &)"
(??4?$image@N@image@@QAEAAV01@ABV01@@Z)


This is a FAQ. Search for "link error templates".

V
Jul 23 '05 #2

P: n/a
That's because you just declare the operator=(...), not define it.
Jul 23 '05 #3

P: n/a
Jef Driesen wrote:
YangWeiQin wrote:
That's because you just declare the operator=(...), not define it.

I only posted the declaration, but in my actual code the implementation
is provided. [...]


Provided WHERE?
Jul 23 '05 #4

P: n/a
On 2005-03-24, Jef Driesen <je********@hotmail.com.nospam> wrote:
I want to have multiple image-like classes (e.g. normal image,
subimage,...). And it should be possible to copy the pixels from one
image type to an image of another type. An example:

image im1(512,512), im2(256,256) // Create two images
range r(0,256);
subimage sub(im,r,r) // Create a subimage
im2 = sub; // Copy pixels from subimage


That's not an example of polymorphic assigment. You don't need
a virtual assignment operator to do that.

You should be able to implement it via the base class assignment operator
along these lines:

base& operator=(const base& x) {
image tmp(x.width(),x.height()); // make it exception safe
for (int i = 0; i < width(); ++i)
for (int j = 0; j < height(); ++j )
tmp.setPixel(i,j,x.getPixel(i,j));
swap(tmp);
}

You want to make sure you're not slicing though. Places where you think you
"need" a virtual assignment operator are also places where you're likely to
slice.

Cheers,
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/
Jul 23 '05 #5

P: n/a
On 2005-03-24, Donovan Rebbechi <ab***@aol.com> wrote:
That's not an example of polymorphic assigment. You don't need
a virtual assignment operator to do that.

You should be able to implement it via the base class assignment operator
along these lines:

base& operator=(const base& x) {
image tmp(x.width(),x.height()); // make it exception safe
for (int i = 0; i < width(); ++i)
for (int j = 0; j < height(); ++j )
tmp.setPixel(i,j,x.getPixel(i,j));
swap(tmp);
}


Actually, I think I'm starting to see what the problem is (one of them anyway).
If your subimage class references but doesn't own memory, then you can't
allocate new memory for it. But with a subimage, you can't even "assign" to it
in this sense, unless you're assigning an image that has the same dimensions as
the subimage.

So that raises the question -- does your "polymorphic assignment" resize and
copy, or does it require the precondition
width()==rhs.width && height()==rhs.height())
? It's a bad idea to have a polymorphic function do two substantially
different things for different types. For example, what does this do ?
void foo (base& lhs, base& rhs ) { lhs = rhs; }

My suggestion would be to use assignment in the usual idiomatic C++ way:
primarily as a copy-assign, secondarily as a conversion function.

Write a separate function to handle *element-wise* assignment, and make that
function require that image dimensions match.

Cheers,
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/
Jul 23 '05 #6

P: n/a
Victor Bazarov wrote:
Jef Driesen wrote:
YangWeiQin wrote:
That's because you just declare the operator=(...), not define it.


I only posted the declaration, but in my actual code the
implementation is provided. [...]

Provided WHERE?


In the header file.
Jul 23 '05 #7

P: n/a
Jef Driesen wrote:
Victor Bazarov wrote:
Jef Driesen wrote:
YangWeiQin wrote:

That's because you just declare the operator=(...), not define it.


I only posted the declaration, but in my actual code the
implementation is provided. [...]


Provided WHERE?

In the header file.


OK. Just making sure.
Jul 23 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.