Пожалуйста, проверьте это:
import webbrowser
chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'
webbrowser.get(chrome_path).open('http://docs.python.org/')
Вы не можете этого сделать - после перегрузки оператора ->
вы застряли - перегруженный оператор будет вести себя так же, независимо от того, что от него правильнее.
Вы можете объявить методы Add () и Release () закрытыми и сделать интеллектуальный указатель другом класса подсчета ссылок.
->
должен возвращать указатель или объект, который сам поддерживает оператор ->
. Может быть рекурсивным. Вы не можете сделать так, чтобы оператор ->
вел себя по-разному в зависимости от того, что отображается в правой части ->
.
Я не могу придумать ни одного подход, который не предполагает каким-либо образом реплицировать интерфейсы ваших объектов, на которые указывает ваш объект, или требует, чтобы вы создавали объекты, являющиеся общедоступными, производными от объектов, на которые вы указали, с добавлением и освобождением, скрытыми и сделанными частными в производном классе и с использованием Base * pBase = pDerived; pBase-> Add ();
трюк для вызова добавления и освобождения из интеллектуального указателя.
Я предлагаю вам использовать что-то вроде следующего кода. То, что вы хотите, невозможно , если только вы не хотите добавить небольшое ограничение: объекты должны быть копируемыми (и вы не против использовать эту возможность). В этом случае наследование - хороший вариант.
#include <iostream>
#include <cassert>
using namespace std;
template <class T>
class MySmartPtrHelper : public T
{
public:
MySmartPtrHelper(T* _t)
: m_t(*_t)
{
delete _t;
((T*) this)->Add();
}
~MySmartPtrHelper()
{
((T*) this)->Release();
}
void Add()
{
cout << "MySmartPtrHelper::Add()" << endl;
//will yield a compile-time error
BOOST_STATIC_ASSERT(false)
}
void Release()
{
cout << "MySmartPtrHelper::Release()" << endl;
//will yield a compile-time error
BOOST_STATIC_ASSERT(false)
}
};
template <class T>
class MySmartPtr
{
MySmartPtrHelper<T>* m_helper;
// Uncomment if you want to use boost to manage memory
// boost::shared_ptr<MySmartPtrHelper<T> > m_helper;
public:
MySmartPtr(T* _pT)
: m_helper(new MySmartPtrHelper<T>(_pT))
{
}
MySmartPtrHelper<T>* operator->()
{
return m_helper;
}
};
int main()
{
MySmartPtr<A> pA(new A());
pA->Foo();
//pA->Release(); // this will correctly assert if uncommented.
return 0;
}
Я заставил его работать, изменив перегруженный оператор в MySmartPtr и добавив перегрузку оператор в MySmartPtrHelper:
#include <iostream>
#include <cassert>
using namespace std;
class A
{
public:
void Add()
{
cout << "A::Add" << endl;
}
void Release()
{
cout << "A::Release" << endl;
}
void Foo()
{
cout << "A::Foo" << endl;
}
};
template <class T>
class MySmartPtrHelper
{
T* m_t;
public:
MySmartPtrHelper(T* _t)
: m_t(_t)
{
m_t->Add();
}
~MySmartPtrHelper()
{
m_t->Release();
}
operator T&()
{
return *m_t;
}
T* operator->()
{
return m_t;
}
void Add()
{
cout << "MySmartPtrHelper::Add()" << endl;
assert(false);
}
void Release()
{
cout << "MySmartPtrHelper::Release()" << endl;
assert(false);
}
};
template <class T>
class MySmartPtr
{
MySmartPtrHelper<T> m_helper;
public:
MySmartPtr(T* _pT)
: m_helper(_pT)
{
}
T* operator->()
{
return m_helper.operator->();
}
};
int main()
{
A a;
MySmartPtr<A> pA(&a);
pA->Foo();
//pA->Release(); // this will correctly assert if uncommented.
return 0;
}
Вывод:
macbook-2:~ $ ./a.out
A::Add
A::Foo
A::Release