用std安全指针相互链接的c ++类(c ++)

时间:2015-09-04 14:17:59

标签: c++ oop pointers c++11 weak-ptr

我的项目有问题。我相信来自新c ++ stabdards的共享/弱指针可以解决它,但我不清楚如何。在我读到的关于标准库的书中,没有评论我的想法如何使用这些指针。

在我的应用程序中,我有Library课程。此类具有内部vectorBook个对象。这些对象通常在Library类中创建,但外部代码使用函数从中查询Books对象,并在以后使用它们。每个Book实例都有一个指向“host”Library实例的公共指针。

有时外部代码会删除Library并创建新代码,但它仍然可以使用旧库中以前查询过的Book个对象。我的问题是Book类应该删除不再有效的指针,因此book不会包含指向已删除库实例的无效指针。

我不清楚如何实现书类的弱指针来实现这种行为。

2 个答案:

答案 0 :(得分:1)

有可能。

由于Library需要知道如何添加图书,因此需要知道如何为自己获取weak_ptr。幸运的是,有一个名为enable_shared_from_this的辅助基类允许你这样做。

#include <memory>
#include <iostream>
#include <vector>

class Library;

struct Book {
  std::weak_ptr<Library> host_library;
};

class Library : public std::enable_shared_from_this<Library> {
    std::vector<Book> books;
 public:
  const Book& getBook(size_t index) const { return books.at(index); }
  void addBook() { 
      books.emplace_back();
      books.back().host_library = shared_from_this();
  }
};

int main() {
    auto library = std::make_shared<Library>();
    library->addBook();

    auto book_copy = library->getBook(0);              
    library.reset();                                   // Destroy the library

    auto old_library = book_copy.host_library.lock();  // Try to get a shared_ptr
    if (!old_library)                                  // to the library from the book.
        std::cout << "Library gone!\n";
}

Live demo

要使其正常工作,Library始终需要创建为shared_ptr。您可以通过使构造函数为私有并具有返回shared_ptr的静态创建函数来强制执行该操作。

答案 1 :(得分:0)

我认为弱点不会帮助你。

而是更好地实现Library类。当然图书馆应该知道哪些书属于它。如果删除库,它应该清理其内存并更新属于它的所有对象。

删除库后,本书会发生什么?

而是使用public class Categorii_LIst_Item_Clicked extends ActionBarActivity { static Context context; static Bundle extras; SectionsPagerAdapter mSectionsPagerAdapter; static ImageLoader imageLoader; static DisplayImageOptions options; ViewPager mViewPager; @Override protected void onCreate (Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_categorii__list__item__clicked); context = this; mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); extras = getIntent().getExtras(); mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mSectionsPagerAdapter); //Setup the ImageLoader, we'll use this to display our images ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this).build(); imageLoader = ImageLoader.getInstance(); imageLoader.init(config); //Setup options for ImageLoader so it will handle caching for us. options = new DisplayImageOptions.Builder() .cacheInMemory() .cacheOnDisc() .build(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_categorii__list__item__clicked, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } public class SectionsPagerAdapter extends FragmentPagerAdapter { public SectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { if (position == 0) { return PlaceholderFragment.newInstance(position); } else if (position == 1) { return VideoFragment.newInstance1(position); } return PlaceholderFragment.newInstance(position); } @Override public int getCount() { return 2; } @Override public CharSequence getPageTitle(int position) { Locale l = Locale.getDefault(); switch (position) { case 0: return getString(R.string.title_section4).toUpperCase(l); case 1: return getString(R.string.title_section5).toUpperCase(l); } return null; } } public static class PlaceholderFragment extends Fragment { private static final String ARG_SECTION_NUMBER = "section_number"; public static PlaceholderFragment newInstance(int sectionNumber) { PlaceholderFragment fragment = new PlaceholderFragment(); Bundle args = new Bundle(); args.putInt(ARG_SECTION_NUMBER, sectionNumber); fragment.setArguments(args); return fragment; } public PlaceholderFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_list_item_clicked, container, false); TextView pDate = (TextView) rootView.findViewById(R.id.textView); pDate.setText(extras.getString("pdate")); TextView ptitle = (TextView) rootView.findViewById(R.id.section_label); ptitle.setText(extras.getString("pname")); TextView pnText = (TextView) rootView.findViewById(R.id.textView2); pnText.setText(extras.getString("pText")); //Setup a listener we can use to swtich from the loading indicator to the Image once it's ready ImageLoadingListener listener = new ImageLoadingListener() { @Override public void onLoadingStarted(String arg0, View arg1) { // TODO Auto-generated method stub } @Override public void onLoadingCancelled(String arg0, View arg1) { // TODO Auto-generated method stub } @Override public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) { // i/ndicator.setVisibility(View.INVISIBLE); // iconImg.setVisibility(View.VISIBLE); } @Override public void onLoadingFailed(String arg0, View arg1, FailReason arg2) { // TODO Auto-generated method stub } }; //Load the image and use our options so caching is handled. final ImageView iconImg = (ImageView) rootView.findViewById(R.id.imageView); imageLoader.displayImage(extras.getString("pImage"), iconImg, options, listener); return rootView; } } public static class VideoFragment extends Fragment { private static final String ARG_SECTION_NUMBER = "section_number"; public static VideoFragment newInstance1(int sectionNumber) { VideoFragment fragment = new VideoFragment(); Bundle args = new Bundle(); args.putInt(ARG_SECTION_NUMBER, sectionNumber); fragment.setArguments(args); return fragment; } public VideoFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.video_fragment, container, false); VideoView myVideoView = (VideoView) rootView.findViewById(R.id.videoView); Uri video = Uri.parse(extras.getString("pVideo")); myVideoView.setMediaController(new MediaController(context)); myVideoView.setVideoURI(video); myVideoView.requestFocus(); //myVideoView.start(); return rootView; } } }