|
-
December 15th, 2006, 01:43 PM
#25
Re: How to avoid dynamic_cast/static_cast
Visitor solution is okay but it does not look better than having members isDir() and isFile() in that these functions would be making 1 virtual call while the visitor solution makes 2. Good that it hides the keywords "*_cast" but I don't think it is well suited here.
For composite pattern, I looked at it the first time and tried pulling out some code that can help achieve the search functionality but it too required knowledge if a FSObject is a folder or not. Here is what I roughly got (incomplete but then I don't feel like completing it):
Code:
#include <iostream>
#include <string>
#include <vector>
class IFSObject
{
public:
virtual const std::vector<IFSObject*>& GetChildren() const = 0;
virtual const std::string& GetName() const = 0
virtual IFSObject& Clone() = 0;
//other interfaces
virtual ~IFSObject(){}
};
class File : public IFSObject
{
public:
File(const std::string& name_) : name(name_){}
const std::vector<IFSObject*>& GetChildren() const{
return std::vector<IFSObject*>();
}
const std::string& GetName() const{
return name;
}
IFSObject& Clone(){
return *(new File(name));
}
private:
std::string name;
}
class Folder : public IFSObject
{
public:
Folder(const std::string& name_) : name(name_){}
const std::vector<IFSObject*>& GetChildren() const{
return children;
}
void Add(const IFSObject& something){
/*Should keep IFSObject ownership*/
children.push_back(&(something.Clone()));
}
void Remove(const IFSObject& something){
/*Add remove logic*/
}
IFSObject& Clone(){
return *(new Folder(name));
}
~Folder(){
/*Add children cleanup logic*/
}
private:
std::string name;
std::vector<IFSObject*> children; /*may use shared_ptr<T>*/
}
class Link : public IFSObject
{
/*add implementations with extensions*/
}
IFSObject* search(const std::string& name, const Folder& folder)
{
//would need to know the actual type
//Why??
//Because there can be empty folders and links which will not be files.
}
int main()
{
//create a filesystem
Folder folder;
//fill folder with various components
IFSObject* fsobject_ptr = search("somefile", folder);
return 0;
}
Or else, I might not have understood composite pattern well. But the thing is the moment a differentiation is necessary (which I think is), the composite pattern becomes a wrong choice.
Having a variant type might not help as well. Type information seems necessary. A virtual call is necessary.
There is one advantage with composite pattern though - the virtual call to know the type would be only necessary in the worst cases, i.e. when a directory does not have files and the cases when the FSObject may be a link. For the rest of the iteration one can go without knowing what FSObject* actually points to. That is a choice you can make.
I also had a quick look at boost::filesystem library where I though they might be having some different solution when finding files in a filesystem. But, alas, they don't have any such mechanism either. They also need to know the "type" information. They use a function named "is_directory". Take a look at the following code:
Code:
bool find_file( const path & dir_path, // in this directory,
const std::string & file_name, // search for this name,
path & path_found ) // placing path here if found
{
if ( !exists( dir_path ) )
return false;
directory_iterator end_itr; // default construction yields past-the-end
for ( directory_iterator itr( dir_path ); itr != end_itr; ++itr )
{
if ( is_directory( *itr ) )
{
if ( find_file( *itr, file_name, path_found ) ) return true;
}
else if ( itr->leaf() == file_name ) // see below
{
path_found = *itr;
return true;
}
}
return false;
}
So as to conclude my thoughts on this now, there are 2 options: go ahead with what you have already (something as in OP) or use composite pattern with type checking in worst cases. That can be reduced even further with one thing that I am not very sure of - but atleast in *nix and windows doing ls -altr or dir, I always see 2 entries (directories . and ..) may be paths to previous directory and current working directory. This may be a case worth considering whatever you are modelling (I think that is not actually a FS).
Hope it helps a little bit.
Last edited by exterminator; December 15th, 2006 at 01:45 PM.
Can you help me with my homework assignment?, Before you post!, Use code tags, How to post!, Codeguru technical FAQs, C++ FAQ Lite, Stroustrup: C++ Style and Technique FAQ, Guru of the Week, Comeau C and C++ FAQs, Comeau C++ Templates FAQs, CUJ @ DDJ, Spam threshold
My Blogs : Learning C++ is fun | Abnegator's reflections
Open Threads : C++ Aha! Moments | Nature of work in C++?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|