473,413 Members | 1,794 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,413 software developers and data experts.

specifying interface without definition?

Hello!

Suppose I'm writing a library to write a binary representation
of some data to a stream. Let's say that to make it extensible
in the future I'm preceding the actual data with some info
like the number of fields, total length, etc. that make up
some kind of header, assuming the actual data may change
over time.

I was hoping to implement a 'class datafile' that would
represent the whole datafile, a 'class record' which would
consist of a header and the actual data. I want the 'record'
class to have a member to write it to a stream, like

record::write(ostream &out) {
// write record number
// write other stuff like sizeof(actual_data)
// write actual_data
}

I was aiming for a design that would allow the class
actual_data to vary, ie. NOT be defined in the library
I'm writing, but be defined in the program that uses
the library. Then I would write programs that would
define their own actual_data class and use the library
to store records into a datafile.

To make the library independent of actual_data I
have decided to only store a pointer to it, so the
record class would look like this
class record {
// some header data
actual_data *content;
}

Now, it turns out that if actual_data is non-POD then
I must provide some means to serialize it, like overloading
<< and >> or providing some save_to_bytes()/restore_from_bytes()
members. These would be used in record::write during
'write actual_data'. Of course these would have to be supplied
by the program using the library, as they depend on the precise
content of actual_data.

The problem is -- how do I convince the library that I can
call these functions using -> on the pointer to actual_data?
Obviously the library doesn't know what actual_data looks like...

So is there any way to tell the compiler "OK, I have a class
called actual_data that has some fields you don't know in
advance, so I can't give you a definition yet, but it definitely
has some get/put methods so you'll know how to store and restore
it?"

It would also be useful if actual_data could pass some info
to the library, like a 'my_size()' member function, but the
same problem occurs.

So how do I tell the compiler that I have a class that supports
some interface without revealing the whole class definition?

thanks in advance,
- J.
Dec 5 '05 #1
3 1634
Jacek Dziedzic wrote:
Hello!

Suppose I'm writing a library to write a binary representation
of some data to a stream. Let's say that to make it extensible
in the future I'm preceding the actual data with some info
like the number of fields, total length, etc. that make up
some kind of header, assuming the actual data may change
over time.

I was hoping to implement a 'class datafile' that would
represent the whole datafile, a 'class record' which would
consist of a header and the actual data. I want the 'record'
class to have a member to write it to a stream, like

record::write(ostream &out) {
// write record number
// write other stuff like sizeof(actual_data)
// write actual_data
}

I was aiming for a design that would allow the class
actual_data to vary, ie. NOT be defined in the library
I'm writing, but be defined in the program that uses
the library. Then I would write programs that would
define their own actual_data class and use the library
to store records into a datafile.

To make the library independent of actual_data I
have decided to only store a pointer to it, so the
record class would look like this
class record {
// some header data
actual_data *content;
}

Now, it turns out that if actual_data is non-POD then
I must provide some means to serialize it, like overloading
<< and >> or providing some save_to_bytes()/restore_from_bytes()
members. These would be used in record::write during
'write actual_data'. Of course these would have to be supplied
by the program using the library, as they depend on the precise
content of actual_data.

The problem is -- how do I convince the library that I can
call these functions using -> on the pointer to actual_data?
Obviously the library doesn't know what actual_data looks like...

So is there any way to tell the compiler "OK, I have a class
called actual_data that has some fields you don't know in
advance, so I can't give you a definition yet, but it definitely
has some get/put methods so you'll know how to store and restore
it?"

It would also be useful if actual_data could pass some info
to the library, like a 'my_size()' member function, but the
same problem occurs.

So how do I tell the compiler that I have a class that supports
some interface without revealing the whole class definition?

thanks in advance,
- J.


This is a classic case for templates. Your actual_data class can be a
template parameter to the datafile and/or record class.

#include <ostream>
#include <string>

template< class ActualData >
class DataFile
{
void SerializeTo( std::ostream& os )
{
os << actualData_;
}
// ...
private:
ActualData actualData_;
};

struct MyData
{
std::string name;
int id;
};

std::ostream operator<<( std::ostream& os, const MyData& data )
{
os << data.name << ' ' << data.id << std::endl;
return os;
};

void Foo()
{
DataFile<MyData> myDataFile;
// ...
myDataFile.SerializeTo( std::cout );
}

Cheers! --M

Dec 5 '05 #2
"Jacek Dziedzic" <jacek@no_spam.tygrys.no_spam.net> schrieb im Newsbeitrag
news:86**************************@news.chello.pl.. .
....
I was aiming for a design that would allow the class
actual_data to vary, ie. NOT be defined in the library
I'm writing, but be defined in the program that uses
the library. Then I would write programs that would
define their own actual_data class and use the library
to store records into a datafile.

To make the library independent of actual_data I
have decided to only store a pointer to it, so the
record class would look like this
class record {
// some header data
actual_data *content;
}

Now, it turns out that if actual_data is non-POD then
I must provide some means to serialize it, like overloading
<< and >> or providing some save_to_bytes()/restore_from_bytes()
members. These would be used in record::write during
'write actual_data'. Of course these would have to be supplied
by the program using the library, as they depend on the precise
content of actual_data.

The problem is -- how do I convince the library that I can
call these functions using -> on the pointer to actual_data?
Obviously the library doesn't know what actual_data looks like...


That's (also) what inheritance has been invented for. In your library you
can define some class, that defines all methods your library needs to call.
But you do not provide an implementation of those methods. Instead you
declare them as pure virtual functions. The only function, which you should
implement, is an empty, virtual destructor. You define this class in a
header file, which is used both in your library and the programs using the
library.

If your library only needs to read and write binary data from/to a stream,
such an interface yould look like

class AbstractData
{
public:
virtual ~AbstractData() {}
virtual int read(istream& stream, char* buffer, size_t bytesToRead)
= 0;
virtual int write(istream& stream, char* buffer, size_t
bytesWritten) = 0;
};

A program using your library can define its own class derived from
AbstractData. It must implement all pure virtual methods of its base class,
otherwise it would not be possible to create an instance of that class. Any
decent compiler will take care of that. Such an implementation could look
like this (I'll leave the actual implementation as an exercise :-)

class ConcretData: public AbstractData
{
int read(istream& stream, char* buffer, size_t bytesToRead);
int write(istream& stream, char* buffer, size_t bytesWritten);
// ...
// More stuff, that is not directly used by your library
};

If you like it, you can repeat "virtual" for all functions inherrited from
AbstractBase, but you don't have to. Once a function has been declared
virtual it will remaon so in all derived classes. That's also why there
should be an empty, virtual destructor in your base class. Even though there
is no data, that needs to be destructed, the virtual destructor allows you
to delete an instance of any derived class through a pointer to your
abstract base.

HTH
Heinz
Dec 5 '05 #3

Thanks a lot for the responses. I'd try the template way.

- J.
Dec 6 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Ole Olsen | last post by:
Hi Any input on what is best practice: 1 ) Put an Interface definition (e.g. IMyInterface) into a separate Assembly 2 ) Put the Interface definirion into the same assembly that holds the...
21
by: Helge Jensen | last post by:
I've got some data that has Set structure, that is membership, insert and delete is fast (O(1), hashing). I can't find a System.Collections interface that matches the operations naturally offered...
7
by: Charles Law | last post by:
Can anyone convert the following C++ interface definition to VB.NET? I have had a go, but I cannot make the Load function work and the IsDirty function gives an error (Object not set to an...
0
by: Mark | last post by:
I create a simple interface in a com object: public interface ISimple { void a(); int b(); } I build the object in Visual Studio and load the object from Excel. I can call a and b...
4
by: Ray Dukes | last post by:
What I am looking to do is map the implementation of interface properties and functions to an inherited method of the base class. Please see below. ...
4
by: Raja Chandrasekaran | last post by:
Hai friends, I really wonder, If the interface does not have any definition, Y do we need to use interface. You can then only we can use Multiple inheritance. I really cant understand, Just for...
1
by: /M | last post by:
Hi! As you know, one way to seperate platform dependent code from platform _independent_ code is to create an abstract base class which acts as an interface towards all platform independent code...
15
by: Xah Lee | last post by:
On Java's Interface Xah Lee, 20050223 In Java the language, there's this a keyword “interface”. In a functional language, a function can be specified by its name and parameter specs....
52
by: Ben Voigt [C++ MVP] | last post by:
I get C:\Programming\LTM\devtools\UselessJunkForDissassembly\Class1.cs(360,27): error CS0535: 'UselessJunkForDissassembly.InvocableInternals' does not implement interface member...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.